Commit 95c6fe09 authored by jim's avatar jim

Added newest keyword parameter to the install and build functions to

allow for getting less than the newest but still getting what's
necessary.


git-svn-id: http://svn.zope.org/repos/main/zc.buildout/trunk@72383 62d5b8a3-27da-0310-9561-8e5933582275
parent 8f9e737a
############################################################################## #############################################################################
# #
# Copyright (c) 2005 Zope Corporation and Contributors. # Copyright (c) 2005 Zope Corporation and Contributors.
# All Rights Reserved. # All Rights Reserved.
...@@ -85,80 +85,7 @@ def _get_index(executable, index_url, find_links): ...@@ -85,80 +85,7 @@ def _get_index(executable, index_url, find_links):
_indexes[key] = index _indexes[key] = index
return index return index
def _satisfied(req, env, dest, executable, index, links): clear_index_cache = _indexes.clear
dists = [dist for dist in env[req.project_name] if dist in req]
if not dists:
logger.debug('We have no distributions for %s', req.project_name)
return None
# Note that dists are sorted from best to worst, as promised by
# env.__getitem__
for dist in dists:
if (dist.precedence == pkg_resources.DEVELOP_DIST):
logger.debug('We have a develop egg for %s', req)
return dist
# Find an upprt limit in the specs, if there is one:
specs = [(pkg_resources.parse_version(v), op) for (op, v) in req.specs]
specs.sort()
maxv = None
greater = False
lastv = None
for v, op in specs:
if op == '==' and not greater:
maxv = v
elif op in ('>', '>=', '!='):
maxv = None
greater == True
elif op == '<':
maxv = None
greater == False
elif op == '<=':
maxv = v
greater == False
if v == lastv:
# Repeated versions values are undefined, so
# all bets are off
maxv = None
greater = True
else:
lastv = v
best_we_have = dists[0] # Because dists are sorted from best to worst
# Check if we have the upper limit
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
# We have some installed distros. There might, theoretically, be
# newer ones. Let's find out which ones are available and see if
# any are newer. We only do this if we're willing to install
# something, which is only true if dest is not None:
if dest is not None:
best_available = _get_index(executable, index, links).obtain(req)
else:
best_available = None
if best_available is None:
# That's a bit odd. There aren't any distros available.
# We should use the best one we have that meets the requirement.
logger.debug(
'There are no distros available that meet %s. Using our best.', req)
return best_we_have
else:
# Let's find out if we already have the best available:
if best_we_have.parsed_version >= best_available.parsed_version:
# Yup. Use it.
logger.debug('We have the best distribution that satisfies\n%s', req)
return best_we_have
return None
if sys.platform == 'win32': if sys.platform == 'win32':
# work around spawn lamosity on windows # work around spawn lamosity on windows
...@@ -172,293 +99,384 @@ _easy_install_cmd = _safe_arg( ...@@ -172,293 +99,384 @@ _easy_install_cmd = _safe_arg(
'from setuptools.command.easy_install import main; main()' 'from setuptools.command.easy_install import main; main()'
) )
def _call_easy_install(spec, env, ws, dest, links, index, class Installer:
executable, always_unzip):
def __init__(self,
path = _get_dist(pkg_resources.Requirement.parse('setuptools'), dest=None,
env, ws, dest, links, index, executable, False).location links=(),
index=None,
args = ('-c', _easy_install_cmd, '-mUNxd', _safe_arg(dest)) executable=sys.executable,
if always_unzip: always_unzip=False,
args += ('-Z', ) path=None,
level = logger.getEffectiveLevel() newest=True,
if level > logging.DEBUG: ):
args += ('-q', ) self._dest = dest
elif level < logging.DEBUG: self._links = list(links)
args += ('-v', ) self._index_url = index
self._executable = executable
args += (spec, ) self._always_unzip = always_unzip
path = (path and path[:] or []) + buildout_and_setuptools_path
if dest is not None and dest not in path:
path.insert(0, dest)
self._path = path
self._newest = newest
self._env = pkg_resources.Environment(path,
python=_get_version(executable))
self._index = _get_index(executable, index, links)
def _satisfied(self, req):
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', req.project_name)
return None
# Note that dists are sorted from best to worst, as promised by
# env.__getitem__
for dist in dists:
if (dist.precedence == pkg_resources.DEVELOP_DIST):
logger.debug('We have a develop egg for %s', req)
return dist
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]
# Find an upprt limit in the specs, if there is one:
specs = [(pkg_resources.parse_version(v), op) for (op, v) in req.specs]
specs.sort()
maxv = None
greater = False
lastv = None
for v, op in specs:
if op == '==' and not greater:
maxv = v
elif op in ('>', '>=', '!='):
maxv = None
greater == True
elif op == '<':
maxv = None
greater == False
elif op == '<=':
maxv = v
greater == False
if v == lastv:
# Repeated versions values are undefined, so
# all bets are off
maxv = None
greater = True
else:
lastv = v
if level <= logging.DEBUG: best_we_have = dists[0] # Because dists are sorted from best to worst
logger.debug('Running easy_install:\n%s "%s"\npath=%s\n',
executable, '" "'.join(args), path)
args += (dict(os.environ, PYTHONPATH=path), ) # Check if we have the upper limit
sys.stdout.flush() # We want any pending output first if maxv is not None and best_we_have.version == maxv:
exit_code = os.spawnle(os.P_WAIT, executable, executable, *args) logger.debug('We have the best distribution that satisfies\n%s',
assert exit_code == 0 req)
return best_we_have
# We have some installed distros. There might, theoretically, be
# newer ones. Let's find out which ones are available and see if
# any are newer. We only do this if we're willing to install
# something, which is only true if dest is not None:
def _get_dist(requirement, env, ws,
dest, links, index_url, executable, always_unzip): if self._dest is not None:
best_available = self._index.obtain(req)
# Maybe an existing dist is already the best dist that satisfies the else:
# requirement best_available = None
dist = _satisfied(requirement, env, dest, executable, index_url, links)
if best_available is None:
# That's a bit odd. There aren't any distros available.
# We should use the best one we have that meets the requirement.
logger.debug(
'There are no distros available that meet %s. Using our best.',
req)
return best_we_have
else:
# Let's find out if we already have the best available:
if best_we_have.parsed_version >= best_available.parsed_version:
# Yup. Use it.
logger.debug(
'We have the best distribution that satisfies\n%s',
req)
return best_we_have
if dist is None: return None
if dest is not None:
logger.info("Getting new distribution for %s", requirement)
# Retrieve the dist: def _call_easy_install(self, spec, ws, dest):
index = _get_index(executable, index_url, links)
dist = index.obtain(requirement)
if dist is None:
raise zc.buildout.UserError(
"Couldn't find a distribution for %s."
% requirement)
fname = dist.location path = self._get_dist(pkg_resources.Requirement.parse('setuptools'),
if url_match(fname): ws, False).location
fname = urlparse.urlparse(fname)[2]
args = ('-c', _easy_install_cmd, '-mUNxd', _safe_arg(dest))
if fname.endswith('.egg'): if self._always_unzip:
# It's already an egg, just fetch it into the dest args += ('-Z', )
tmp = tempfile.mkdtemp('get_dist') level = logger.getEffectiveLevel()
try: if level > logging.DEBUG:
dist = index.fetch_distribution(requirement, tmp) args += ('-q', )
if dist is None: elif level < logging.DEBUG:
raise zc.buildout.UserError( args += ('-v', )
"Couln't download a distribution for %s."
% requirement) args += (spec, )
newloc = os.path.join( if level <= logging.DEBUG:
dest, os.path.basename(dist.location)) logger.debug('Running easy_install:\n%s "%s"\npath=%s\n',
executable, '" "'.join(args), path)
if os.path.isdir(dist.location):
# we got a directory. It must have been args += (dict(os.environ, PYTHONPATH=path), )
# obtained locally. Jut copy it. sys.stdout.flush() # We want any pending output first
shutil.copytree(dist.location, newloc) exit_code = os.spawnle(os.P_WAIT, self._executable, self._executable,
else: *args)
assert exit_code == 0
if always_unzip:
should_unzip = True
else: def _get_dist(self, requirement, ws, always_unzip):
metadata = pkg_resources.EggMetadata(
zipimport.zipimporter(dist.location) # Maybe an existing dist is already the best dist that satisfies the
) # requirement
should_unzip = ( dist = self._satisfied(requirement)
metadata.has_metadata('not-zip-safe')
or not metadata.has_metadata('zip-safe') if dist is None:
) if self._dest is not None:
logger.info("Getting new distribution for %s", requirement)
if should_unzip:
setuptools.archive_util.unpack_archive( # Retrieve the dist:
dist.location, newloc) index = self._index
dist = index.obtain(requirement)
if dist is None:
raise zc.buildout.UserError(
"Couldn't find a distribution for %s."
% requirement)
fname = dist.location
if url_match(fname):
fname = urlparse.urlparse(fname)[2]
if fname.endswith('.egg'):
# 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))
if os.path.isdir(dist.location):
# we got a directory. It must have been
# obtained locally. Jut copy it.
shutil.copytree(dist.location, newloc)
else: else:
shutil.copyfile(dist.location, newloc)
finally:
shutil.rmtree(tmp)
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)
finally:
shutil.rmtree(tmp)
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)
# May need a new one. Call easy_install
self._call_easy_install(dist.location, ws, self._dest)
finally:
shutil.rmtree(tmp)
# Because we have added a new egg, we need to rescan
# the destination directory.
# 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: else:
# It's some other kind of dist. We'll download it to dist = self._env.best_match(requirement, ws)
# 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)
# May need a new one. Call easy_install
_call_easy_install(
dist.location, env, ws, dest, links, index_url,
executable, always_unzip)
finally:
shutil.rmtree(tmp)
# Because we have added a new egg, we need to rescan
# the destination directory.
# We may overwrite distributions, so clear importer
# cache.
sys.path_importer_cache.clear()
env.scan([dest])
dist = env.best_match(requirement, ws)
logger.info("Got %s", dist)
else:
dist = env.best_match(requirement, ws)
if dist is None: if dist is None:
raise ValueError("Couldn't find", requirement) raise ValueError("Couldn't find", requirement)
# XXX Need test for this # XXX Need test for this
if dist.has_metadata('dependency_links.txt'): if dist.has_metadata('dependency_links.txt'):
for link in dist.get_metadata_lines('dependency_links.txt'): for link in dist.get_metadata_lines('dependency_links.txt'):
link = link.strip() link = link.strip()
if link not in links: if link not in self._links:
links.append(link) self._links.append(link)
self._index = _get_index(self._executable,
return dist self._index_url, self._links)
return dist
def _maybe_add_setuptools(self, ws, dist):
if dist.has_metadata('namespace_packages.txt'):
for r in dist.requires():
if r.project_name == 'setuptools':
break
else:
# We have a namespace package but no requirement for setuptools
if dist.precedence == pkg_resources.DEVELOP_DIST:
logger.warn(
"Develop distribution for %s\n"
"uses namespace packages but the distribution "
"does not require setuptools.",
dist)
requirement = pkg_resources.Requirement.parse('setuptools')
if ws.find(requirement) is None:
dist = self._get_dist(requirement, ws, False)
ws.add(dist)
def _maybe_add_setuptools(ws, dist, env, dest, links, index, executable):
if dist.has_metadata('namespace_packages.txt'):
for r in dist.requires():
if r.project_name == 'setuptools':
break
else:
# We have a namespace package but no requirement for setuptools
if dist.precedence == pkg_resources.DEVELOP_DIST:
logger.warn(
"Develop distribution for %s\n"
"uses namespace packages but the distribution "
"does not require setuptools.",
dist)
requirement = pkg_resources.Requirement.parse('setuptools')
if ws.find(requirement) is None:
dist = _get_dist(requirement, env, ws,
dest, links, index, executable,
False)
ws.add(dist)
def install(specs, dest,
links=(), index=None,
executable=sys.executable, always_unzip=False,
path=None, working_set=None):
logger.debug('Installing %r', specs) def install(self, specs, working_set=None):
path = path and path[:] or [] logger.debug('Installing %r', specs)
if dest is not None and dest not in path:
path.insert(0, dest)
path += buildout_and_setuptools_path path = self._path
dest = self._dest
if dest is not None and dest not in path:
path.insert(0, dest)
links = list(links) # make copy, because we may need to mutate requirements = [pkg_resources.Requirement.parse(spec)
for spec in specs]
# For each spec, see if it is already installed. We create a working if working_set is None:
# set to keep track of what we've collected and to make sue than the ws = pkg_resources.WorkingSet([])
# distributions assembled are consistent. else:
env = pkg_resources.Environment(path, python=_get_version(executable)) ws = working_set
requirements = [pkg_resources.Requirement.parse(spec) for spec in specs]
if working_set is None: for requirement in requirements:
ws = pkg_resources.WorkingSet([]) dist = self._get_dist(requirement, ws, self._always_unzip)
else:
ws = working_set
for requirement in requirements:
dist = _get_dist(requirement, env, ws,
dest, links, index, executable, always_unzip)
ws.add(dist)
_maybe_add_setuptools(ws, dist,
env, dest, links, index, executable)
# OK, we have the requested distributions and they're in the working
# set, but they may have unmet requirements. We'll simply keep
# trying to resolve requirements, adding missing requirements as they
# are reported.
#
# Note that we don't pass in the environment, because we
# want to look for new eggs unless what we have is the best that matches
# the requirement.
while 1:
try:
ws.resolve(requirements)
except pkg_resources.DistributionNotFound, err:
[requirement] = err
if dest:
logger.debug('Getting required %s', requirement)
dist = _get_dist(requirement, env, ws,
dest, links, index, executable, always_unzip)
ws.add(dist) ws.add(dist)
_maybe_add_setuptools(ws, dist, self._maybe_add_setuptools(ws, dist)
env, dest, links, index, executable)
else: # OK, we have the requested distributions and they're in the working
break # set, but they may have unmet requirements. We'll simply keep
# trying to resolve requirements, adding missing requirements as they
return ws # are reported.
#
# Note that we don't pass in the environment, because we
# want to look for new eggs unless what we have is the best that matches
# the requirement.
while 1:
try:
ws.resolve(requirements)
except pkg_resources.DistributionNotFound, err:
[requirement] = err
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)
else:
break
def build(spec, dest, build_ext, return ws
links=(), index=None,
executable=sys.executable,
path=None):
index_url = index def build(self, spec, build_ext):
logger.debug('Building %r', spec)
logger.debug('Building %r', spec) requirement = pkg_resources.Requirement.parse(spec)
path = path and path[:] or [] dist = self._satisfied(requirement)
if dest is not None: if dist is not None:
path.insert(0, dest) return dist.location
path += buildout_and_setuptools_path undo = []
try:
tmp = tempfile.mkdtemp('build')
undo.append(lambda : shutil.rmtree(tmp))
tmp2 = tempfile.mkdtemp('build')
undo.append(lambda : shutil.rmtree(tmp2))
links = list(links) # make copy, because we may need to mutate dist = self._index.fetch_distribution(
requirement, tmp2, False, True)
# For each spec, see if it is already installed. We create a working if dist is None:
# set to keep track of what we've collected and to make sue than the raise zc.buildout.UserError(
# distributions assembled are consistent. "Couldn't find a source distribution for %s."
env = pkg_resources.Environment(path, python=_get_version(executable)) % requirement)
requirement = pkg_resources.Requirement.parse(spec) setuptools.archive_util.unpack_archive(dist.location, tmp)
dist = _satisfied(requirement, env, dest, executable, index_url, links) if os.path.exists(os.path.join(tmp, 'setup.py')):
if dist is not None: base = tmp
return [dist.location] 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])
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))
undo = [] tmp3 = tempfile.mkdtemp('build', dir=self._dest)
try: undo.append(lambda : shutil.rmtree(tmp3))
tmp = tempfile.mkdtemp('build')
undo.append(lambda : shutil.rmtree(tmp))
tmp2 = tempfile.mkdtemp('build')
undo.append(lambda : shutil.rmtree(tmp2))
index = _get_index(executable, index_url, links) self._call_easy_install(base, pkg_resources.WorkingSet(), tmp3)
dist = 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)
if os.path.exists(os.path.join(tmp, 'setup.py')): return _copyeggs(tmp3, self._dest, '.egg', undo)
base = 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])
finally:
undo.reverse()
[f() for f in undo]
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))
tmp3 = tempfile.mkdtemp('build', dir=dest) def install(specs, dest,
undo.append(lambda : shutil.rmtree(tmp3)) links=(), index=None,
executable=sys.executable, always_unzip=False,
path=None, working_set=None, newest=True):
installer = Installer(dest, links, index, executable, always_unzip, path,
newest)
return installer.install(specs, working_set)
_call_easy_install(base, env, pkg_resources.WorkingSet(),
tmp3, links, index_url, executable, True)
return _copyeggs(tmp3, dest, '.egg', undo) def build(spec, dest, build_ext,
links=(), index=None,
finally: executable=sys.executable,
undo.reverse() path=None, newest=True):
[f() for f in undo] installer = Installer(dest, links, index, executable, True, path, newest)
return installer.build(spec, build_ext)
def _rm(*paths): def _rm(*paths):
...@@ -477,8 +495,8 @@ def _copyeggs(src, dest, suffix, undo): ...@@ -477,8 +495,8 @@ def _copyeggs(src, dest, suffix, undo):
_rm(new) _rm(new)
os.rename(os.path.join(src, name), new) os.rename(os.path.join(src, name), new)
result.append(new) result.append(new)
assert len(result) == 1 assert len(result) == 1, str(result)
undo.pop() undo.pop()
return result[0] return result[0]
......
...@@ -21,7 +21,10 @@ level that is similar to easy_install, with a few exceptions: ...@@ -21,7 +21,10 @@ level that is similar to easy_install, with a few exceptions:
- Distutils options for building extensions can be passed. - Distutils options for building extensions can be passed.
The easy_install module provides a method, install, for installing one Distribution installation
-------------------------
The easy_install module provides a function, install, for installing one
or more packages and their dependencies. The install function takes 2 or more packages and their dependencies. The install function takes 2
positional arguments: positional arguments:
...@@ -68,6 +71,13 @@ working_set ...@@ -68,6 +71,13 @@ working_set
you to call install multiple times, if necessary, to gather you to call install multiple times, if necessary, to gather
multiple sets of requirements. multiple sets of requirements.
newest
A boolian value indicating whether to search for new distributions
when already-installed distributions meet the requirement. When
this is true, the default, and when the destination directory is
not None, then the install function will search for the newest
distributions that satisfy the requirements.
The install method returns a working set containing the distributions The install method returns a working set containing the distributions
needed to meet the given requirements. needed to meet the given requirements.
...@@ -111,8 +121,17 @@ And the actual eggs were added to the eggs directory. ...@@ -111,8 +121,17 @@ And the actual eggs were added to the eggs directory.
- demo-0.2-py2.4.egg - demo-0.2-py2.4.egg
- demoneeded-1.1-py2.4.egg - demoneeded-1.1-py2.4.egg
If we ask for the demo distribution without a version restriction, If we remove the version restriction on demo, but specify a false
we'll get the newer version: value for newest, no new didstributions will be installed:
>>> ws = zc.buildout.easy_install.install(
... ['demo'], dest, links=[link_server], index=link_server+'index/',
... newest=False)
>>> ls(dest)
- demo-0.2-py2.4.egg
- demoneeded-1.1-py2.4.egg
If we leave off the newst option, we'll get an update for demo:
>>> ws = zc.buildout.easy_install.install( >>> ws = zc.buildout.easy_install.install(
... ['demo'], dest, links=[link_server], index=link_server+'index/') ... ['demo'], dest, links=[link_server], index=link_server+'index/')
...@@ -480,9 +499,13 @@ path ...@@ -480,9 +499,13 @@ path
A list of additional directories to search for locally-installed A list of additional directories to search for locally-installed
distributions. distributions.
always_unzip newest
A flag indicating that newly-downloaded distributions should be A boolian value indicating whether to search for new distributions
directories even if they could be installed as zip files. when already-installed distributions meet the requirement. When
this is true, the default, and when the destination directory is
not None, then the install function will search for the newest
distributions that satisfy the requirements.
Our link server included a source distribution that includes a simple Our link server included a source distribution that includes a simple
extension, extdemo.c:: extension, extdemo.c::
...@@ -534,6 +557,57 @@ Now if we look in our destination directory, we see we have an extdemo egg: ...@@ -534,6 +557,57 @@ Now if we look in our destination directory, we see we have an extdemo egg:
d demoneeded-1.1-py2.4.egg d demoneeded-1.1-py2.4.egg
d extdemo-1.4-py2.4-unix-i686.egg d extdemo-1.4-py2.4-unix-i686.egg
Let's update our link server with a new version of extdemo:
>>> update_extdemo()
>>> print get(link_server),
<html><body>
<a href="demo-0.1-py2.4.egg">demo-0.1-py2.4.egg</a><br>
<a href="demo-0.2-py2.4.egg">demo-0.2-py2.4.egg</a><br>
<a href="demo-0.3-py2.4.egg">demo-0.3-py2.4.egg</a><br>
<a href="demoneeded-1.0.zip">demoneeded-1.0.zip</a><br>
<a href="demoneeded-1.1.zip">demoneeded-1.1.zip</a><br>
<a href="extdemo-1.4.zip">extdemo-1.4.zip</a><br>
<a href="extdemo-1.5.zip">extdemo-1.5.zip</a><br>
<a href="index/">index/</a><br>
<a href="other-1.0-py2.4.egg">other-1.0-py2.4.egg</a><br>
</body></html>
The easy_install caches information about servers to reduce network
access. To see the update, we have to call the clear_index_cache
function to clear the index cache:
>>> zc.buildout.easy_install.clear_index_cache()
If we run build with newest set to False, we won't get an update:
>>> zc.buildout.easy_install.build(
... 'extdemo', dest,
... {'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'
>>> ls(dest)
d demo-0.3-py2.4.egg
d demoneeded-1.1-py2.4.egg
d extdemo-1.4-py2.4-unix-i686.egg
But if we run it with the default True setting for newest, then we'll
get an updated egg:
>>> zc.buildout.easy_install.build(
... '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'
d demo-0.3-py2.4.egg
d demoneeded-1.1-py2.4.egg
d extdemo-1.4-py2.4-unix-i686.egg
d extdemo-1.5-py2.4-unix-i686.egg
Handling custom build options for extensions in develop eggs Handling custom build options for extensions in develop eggs
------------------------------------------------------------ ------------------------------------------------------------
...@@ -586,6 +660,7 @@ egg link: ...@@ -586,6 +660,7 @@ egg link:
d demo-0.3-py2.4.egg d demo-0.3-py2.4.egg
d demoneeded-1.1-py2.4.egg d demoneeded-1.1-py2.4.egg
d extdemo-1.4-py2.4-linux-i686.egg d extdemo-1.4-py2.4-linux-i686.egg
d extdemo-1.5-py2.4-linux-i686.egg
- extdemo.egg-link - extdemo.egg-link
And that the source directory contains the compiled extension: And that the source directory contains the compiled extension:
......
...@@ -1047,19 +1047,22 @@ initextdemo(void) ...@@ -1047,19 +1047,22 @@ initextdemo(void)
extdemo_setup_py = """ extdemo_setup_py = """
from distutils.core import setup, Extension from distutils.core import setup, Extension
setup(name = "extdemo", version = "1.4", url="http://www.zope.org", setup(name = "extdemo", version = "%s", url="http://www.zope.org",
author="Demo", author_email="demo@demo.com", author="Demo", author_email="demo@demo.com",
ext_modules = [Extension('extdemo', ['extdemo.c'])], ext_modules = [Extension('extdemo', ['extdemo.c'])],
) )
""" """
def add_source_dist(test): def add_source_dist(test, version=1.4):
tmp = test.globs['extdemo'] = test.globs['tmpdir']('extdemo') if 'extdemo' not in test.globs:
test.globs['extdemo'] = test.globs['tmpdir']('extdemo')
tmp = test.globs['extdemo']
write = test.globs['write'] write = test.globs['write']
try: try:
write(tmp, 'extdemo.c', extdemo_c); write(tmp, 'extdemo.c', extdemo_c);
write(tmp, 'setup.py', extdemo_setup_py); write(tmp, 'setup.py', extdemo_setup_py % version);
write(tmp, 'README', ""); write(tmp, 'README', "");
write(tmp, 'MANIFEST.in', "include *.c\n"); write(tmp, 'MANIFEST.in', "include *.c\n");
test.globs['sdist'](tmp, test.globs['sample_eggs']) test.globs['sdist'](tmp, test.globs['sample_eggs'])
...@@ -1075,7 +1078,9 @@ def easy_install_SetUp(test): ...@@ -1075,7 +1078,9 @@ def easy_install_SetUp(test):
add_source_dist(test) add_source_dist(test)
test.globs['link_server'] = test.globs['start_server']( test.globs['link_server'] = test.globs['start_server'](
test.globs['sample_eggs']) test.globs['sample_eggs'])
test.globs['update_extdemo'] = lambda : add_source_dist(test, 1.5)
egg_parse = re.compile('([0-9a-zA-Z_.]+)-([0-9a-zA-Z_.]+)-py(\d[.]\d).egg$' egg_parse = re.compile('([0-9a-zA-Z_.]+)-([0-9a-zA-Z_.]+)-py(\d[.]\d).egg$'
).match ).match
def makeNewRelease(project, ws, dest): def makeNewRelease(project, ws, dest):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment