[Python-checkins] distutils2: merged upstream

tarek.ziade python-checkins at python.org
Sun Sep 19 10:20:22 CEST 2010


tarek.ziade pushed cc240818f9f9 to distutils2:
http://hg.python.org/distutils2/rev/cc240818f9f9
changeset: 621:cc240818f9f9
parent: 620:b81715424b1c
parent: 556:272a3087dd6e
user: Konrad Delong <konryd at gmail.com>
date: Fri Aug 13 18:19:28 2010 +0200
summary: merged upstream
files: src/distutils2/install_with_deps.py, src/distutils2/tests/test_install_with_deps.py
diff --git a/docs/source/library/distutils2.version.rst b/docs/source/library/distutils2.version.rst
--- a/docs/source/library/distutils2.version.rst
+++ b/docs/source/library/distutils2.version.rst
@@ -5,12 +5,12 @@
 Distutils2 ships with a python package capable to work with version numbers.
 It's an implementation of version specifiers `as defined in PEP 345
 <http://www.python.org/dev/peps/pep-0345/#version-specifiers>`_ about
-Metadata.
+Metadatas.
 
-`distutils2.version.NormalizedVersion`
-======================================
+NormalizedVersion 
+==================
 
-A Normalized version corresponds to a specific version of a distribution, as
+A Normalized version is a specific version of a distribution, as
 described in the PEP 345. So, you can work with the `NormalizedVersion` like
 this::
 
@@ -31,11 +31,12 @@
 
 NormalizedVersion is used internally by `VersionPredicate` to do his stuff.
 
-`distutils2.version.suggest_normalized_version`
------------------------------------------------
+Suggest a normalized version
+----------------------------
 
-You also can let the normalized version be suggested to you, using the
-`suggest_normalized_version` function::
+Before this version scheme, there was existing others ones. Distutils2 provides
+a tool that suggests a normalized version: the `suggest_normalized_version` 
+function::
 
 >>> suggest_normalized_version('2.1-rc1') 
 2.1c1
@@ -46,8 +47,8 @@
 >>> print suggest_normalized_version('not a version')
 None
 
-`distutils2.version.VersionPredicate`
-=====================================
+Dealing with version predicates 
+===============================
 
 `VersionPredicate` knows how to parse stuff like "ProjectName (>=version)", the
 class also provides a `match` method to test if a version number is the version
@@ -59,6 +60,11 @@
 >>> version.match("1.1.1")
 True
 
-`is_valid_predicate`
---------------------
+You could test if a predicate is a valid one, usng the `is_valid_predicate`
+function::
 
+ >>> is_valid_predicate('FooBar (1.1)')
+ True
+ >>> is_valid_predicate('FooBar (+1.1)')
+ False
+
diff --git a/src/distutils2/errors.py b/src/distutils2/errors.py
--- a/src/distutils2/errors.py
+++ b/src/distutils2/errors.py
@@ -80,6 +80,10 @@
 """Byte compile error."""
 
 
+class DistutilsIndexError(DistutilsError):
+ """Any problem occuring during using the indexes."""
+
+
 # Exception classes used by the CCompiler implementation classes
 class CCompilerError(Exception):
 """Some compile/link operation failed."""
diff --git a/src/distutils2/index/errors.py b/src/distutils2/index/errors.py
--- a/src/distutils2/index/errors.py
+++ b/src/distutils2/index/errors.py
@@ -2,30 +2,26 @@
 
 All errors and exceptions raised by PyPiIndex classes.
 """
-from distutils2.errors import DistutilsError
+from distutils2.errors import DistutilsIndexError
 
 
-class IndexesError(DistutilsError):
- """The base class for errors of the index python package."""
-
-
-class ProjectNotFound(IndexesError):
+class ProjectNotFound(DistutilsIndexError):
 """Project has not been found"""
 
 
-class DistributionNotFound(IndexesError):
+class DistributionNotFound(DistutilsIndexError):
 """The release has not been found"""
 
 
-class ReleaseNotFound(IndexesError):
+class ReleaseNotFound(DistutilsIndexError):
 """The release has not been found"""
 
 
-class CantParseArchiveName(IndexesError):
+class CantParseArchiveName(DistutilsIndexError):
 """An archive name can't be parsed to find distribution name and version"""
 
 
-class DownloadError(IndexesError):
+class DownloadError(DistutilsIndexError):
 """An error has occurs while downloading"""
 
 
@@ -33,13 +29,13 @@
 """Compared hashes does not match"""
 
 
-class UnsupportedHashName(IndexesError):
+class UnsupportedHashName(DistutilsIndexError):
 """A unsupported hashname has been used"""
 
 
-class UnableToDownload(IndexesError):
+class UnableToDownload(DistutilsIndexError):
 """All mirrors have been tried, without success"""
 
 
-class InvalidSearchField(IndexesError):
+class InvalidSearchField(DistutilsIndexError):
 """An invalid search field has been used"""
diff --git a/src/distutils2/index/simple.py b/src/distutils2/index/simple.py
--- a/src/distutils2/index/simple.py
+++ b/src/distutils2/index/simple.py
@@ -17,7 +17,7 @@
 from distutils2.index.base import BaseClient
 from distutils2.index.dist import (ReleasesList, EXTENSIONS,
 get_infos_from_url, MD5_HASH)
-from distutils2.index.errors import (IndexesError, DownloadError,
+from distutils2.index.errors import (DistutilsIndexError, DownloadError,
 UnableToDownload, CantParseArchiveName,
 ReleaseNotFound, ProjectNotFound)
 from distutils2.index.mirrors import get_mirrors
@@ -395,7 +395,7 @@
 fp = urllib2.urlopen(request)
 except (ValueError, httplib.InvalidURL), v:
 msg = ' '.join([str(arg) for arg in v.args])
- raise IndexesError('%s %s' % (url, msg))
+ raise DistutilsIndexError('%s %s' % (url, msg))
 except urllib2.HTTPError, v:
 return v
 except urllib2.URLError, v:
diff --git a/src/distutils2/install_with_deps.py b/src/distutils2/install_tools.py
rename from src/distutils2/install_with_deps.py
rename to src/distutils2/install_tools.py
--- a/src/distutils2/install_with_deps.py
+++ b/src/distutils2/install_tools.py
@@ -15,155 +15,79 @@
 """
 
 
-def get_deps(requirements, index):
- """Return the dependencies of a project, as a depgraph object.
-
- Build a :class depgraph.DependencyGraph: for the given requirements
-
- If the project does not uses Metadata < 1.1, dependencies can't be handled
- from here, so it returns an empty list of dependencies.
-
- :param requirements: is a string containing the version predicate to take
- the project name and version specifier from.
- :param index: the index to use for making searches.
- """
- deps = []
- release = index.get_release(requirements)
- requires = release.metadata['Requires-Dist'] + release.metadata['Requires']
- deps.append(release) # include the release we are computing deps.
- for req in requires:
- deps.extend(get_deps(req, index))
- return deps
-
-
-def install(requirements, index=None, interactive=True, upgrade=True,
- prefer_source=True, prefer_final=True):
- """Given a list of distributions to install, a list of distributions to
- remove, and a list of conflicts, proceed and do what's needed to be done.
-
- :param requirements: is a *string* containing the requirements for this
- project (for instance "FooBar 1.1" or "BarBaz (<1.2)
- :param index: If an index is specified, use this one, otherwise, use
- :class index.ClientWrapper: to get project metadatas.
- :param interactive: if set to True, will prompt the user for interactions
- of needed. If false, use the default values.
- :param upgrade: If a project exists in a newer version, does the script
- need to install the new one, or keep the already installed
- version.
- :param prefer_source: used to tell if the user prefer source distributions
- over built dists.
- :param prefer_final: if set to true, pick up the "final" versions (eg.
- stable) over the beta, alpha (not final) ones.
- """
- # get the default index if none is specified
- if not index:
- index = wrapper.WrapperClient()
-
- # check if the project is already installed.
- installed_release = get_installed_release(requirements)
-
- # if a version that satisfy the requirements is already installed
- if installed_release and (interactive or upgrade):
- new_releases = index.get_releases(requirements)
- if (new_releases.get_last(requirements).version >
- installed_release.version):
- if interactive:
- # prompt the user to install the last version of the package.
- # set upgrade here.
- print "You want to install a package already installed on your"
- "system. A new version exists, you could just use the version"
- "you have, or upgrade to the latest version"
-
- upgrade = raw_input("Do you want to install the most recent one ? (Y/n)") or "Y"
- if upgrade in ('Y', 'y'):
- upgrade = True
- else:
- upgrade = False
- if not upgrade:
- return
-
- # create the depgraph from the dependencies of the release we want to
- # install
- graph = generate_graph(get_deps(requirements, index))
- from ipdb import set_trace
- set_trace()
- installed = [] # to uninstall on errors
- try:
- for release in graph.adjacency_list:
- dist = release.get_distribution()
- install(dist)
- installed.append(dist)
- print "%s have been installed on your system" % requirements
- except:
- print "an error has occured, uninstalling"
- for dist in installed:
- uninstall_dist(dist)
-
 class InstallationException(Exception):
 pass
 
-def get_install_info(requirements, index=None, already_installed=None):
+
+def _update_infos(infos, new_infos):
+ """extends the lists contained in the `info` dict with those contained
+ in the `new_info` one
+ """
+ for key, value in infos.items():
+ if key in new_infos:
+ infos[key].extend(new_infos[key])
+
+
+def get_infos(requirements, index=None, installed=None,
+ prefer_final=True):
 """Return the informations on what's going to be installed and upgraded.
 
 :param requirements: is a *string* containing the requirements for this
 project (for instance "FooBar 1.1" or "BarBaz (<1.2)")
 :param index: If an index is specified, use this one, otherwise, use
 :class index.ClientWrapper: to get project metadatas.
- :param already_installed: a list of already installed distributions.
+ :param installed: a list of already installed distributions.
+ :param prefer_final: when picking up the releases, prefer a "final" one
+ over a beta/alpha/etc one.
 
- The results are returned in a dict. For instance::
+ The results are returned in a dict, containing all the operations
+ needed to install the given requirements::
 
 >>> get_install_info("FooBar (<=1.2)")
 {'install': [<FooBar 1.1>], 'remove': [], 'conflict': []}
 
 Conflict contains all the conflicting distributions, if there is a
 conflict.
-
 """
- def update_infos(new_infos, infos):
- for key, value in infos.items():
- if key in new_infos:
- infos[key].extend(new_infos[key])
- return new_infos
 
 if not index:
 index = wrapper.ClientWrapper()
- logging.info("searching releases for %s" % requirements)
 
- # 1. get all the releases that match the requirements
+ if not installed:
+ installed = get_distributions()
+
+ # Get all the releases that match the requirements
 try:
 releases = index.get_releases(requirements)
 except (ReleaseNotFound, ProjectNotFound), e:
- raise InstallationException('Release not found: "%s"' % requirements)
+ raise InstallationException('Release not found: "%s"' % requirements)
 
- # 2. pick up a release, and try to get the dependency tree
- release = releases.get_last(requirements)
+ # Pick up a release, and try to get the dependency tree
+ release = releases.get_last(requirements, prefer_final=prefer_final)
+
+ # Iter since we found something without conflicts
 metadata = release.fetch_metadata()
 
- # 3. get the distributions already_installed on the system
- # 4. and add the one we want to install
- if not already_installed:
- already_installed = get_distributions()
+ # Get the distributions already_installed on the system
+ # and add the one we want to install
 
- logging.info("fetching %s %s dependencies" % (
- release.name, release.version))
- distributions = already_installed + [release]
+ distributions = installed + [release]
 depgraph = generate_graph(distributions)
 
- # store all the already_installed packages in a list, in case of rollback.
- infos = {'install':[], 'remove': [], 'conflict': []}
+ # Store all the already_installed packages in a list, in case of rollback.
+ infos = {'install': [], 'remove': [], 'conflict': []}
 
- # 5. get what the missing deps are
+ # Get what the missing deps are
 for dists in depgraph.missing.values():
 if dists:
 logging.info("missing dependencies found, installing them")
 # we have missing deps
 for dist in dists:
- update_infos(get_install_info(dist, index, already_installed),
- infos)
+ _update_infos(infos,
+ get_infos(dist, index, installed))
 
- # 6. fill in the infos
- existing = [d for d in already_installed if d.name == release.name]
+ # Fill in the infos
+ existing = [d for d in installed if d.name == release.name]
 if existing:
 infos['remove'].append(existing[0])
 infos['conflict'].extend(depgraph.reverse_list[existing[0]])
diff --git a/src/distutils2/tests/test_install_with_deps.py b/src/distutils2/tests/test_install_tools.py
rename from src/distutils2/tests/test_install_with_deps.py
rename to src/distutils2/tests/test_install_tools.py
--- a/src/distutils2/tests/test_install_with_deps.py
+++ b/src/distutils2/tests/test_install_tools.py
@@ -4,10 +4,11 @@
 from distutils2.tests import run_unittest
 from distutils2.tests.support import unittest
 from distutils2.index.xmlrpc import Client
-from distutils2.install_with_deps import (get_install_info, 
+from distutils2.install_tools import (get_infos,
 InstallationException)
 from distutils2.metadata import DistributionMetadata
 
+
 class FakeDist(object):
 """A fake distribution object, for tests"""
 def __init__(self, name, version, deps):
@@ -20,16 +21,25 @@
 def __repr__(self):
 return '<FakeDist %s>' % self.name
 
+
 def get_fake_dists(dists):
 objects = []
 for (name, version, deps) in dists:
- objects.append(FakeDist(name, version, deps))
+ objects.append(FakeDist(name, version, deps))
 return objects
 
+
 class TestInstallWithDeps(unittest.TestCase):
 def _get_client(self, server, *args, **kwargs):
 return Client(server.full_address, *args, **kwargs)
 
+ def _get_results(self, output):
+ """return a list of results"""
+ installed = [(o.name, '%s' % o.version) for o in output['install']]
+ remove = [(o.name, '%s' % o.version) for o in output['remove']]
+ conflict = [(o.name, '%s' % o.version) for o in output['conflict']]
+ return (installed, remove, conflict)
+
 @use_xmlrpc_server()
 def test_existing_deps(self, server):
 # Test that the installer get the dependencies from the metadatas
@@ -55,17 +65,17 @@
 'url': archive_path},
 ])
 installed = get_fake_dists([('bacon', '0.1', []),])
- output = get_install_info("choxie", index=client, 
- already_installed=installed)
+ output = get_infos("choxie", index=client,
+ installed=installed)
 
 # we dont have installed bacon as it's already installed on the system.
 self.assertEqual(0, len(output['remove']))
 self.assertEqual(2, len(output['install']))
- readable_output = [(o.name, '%s' % o.version) 
+ readable_output = [(o.name, '%s' % o.version)
 for o in output['install']]
 self.assertIn(('towel-stuff', '0.1'), readable_output)
 self.assertIn(('choxie', '2.0.0.9'), readable_output)
- 
+
 @use_xmlrpc_server()
 def test_upgrade_existing_deps(self, server):
 # Tests that the existing distributions can be upgraded if needed.
@@ -85,11 +95,11 @@
 'requires_dist': [],
 'url': archive_path},
 ])
- 
- output = get_install_info("choxie", index=client, already_installed= 
- get_fake_dists([('bacon', '0.1', []),]))
+
+ output = get_infos("choxie", index=client, installed=
+ get_fake_dists([('bacon', '0.1', []),]))
 installed = [(o.name, '%s' % o.version) for o in output['install']]
- 
+
 # we need bacon 0.2, but 0.1 is installed.
 # So we expect to remove 0.1 and to install 0.2 instead.
 remove = [(o.name, '%s' % o.version) for o in output['remove']]
@@ -101,7 +111,7 @@
 
 @use_xmlrpc_server()
 def test_conflicts(self, server):
- # Tests that conflicts are detected 
+ # Tests that conflicts are detected
 client = self._get_client(server)
 archive_path = '%s/distribution.tar.gz' % server.full_address
 server.xmlrpc.set_distributions([
@@ -118,16 +128,14 @@
 'requires_dist': [],
 'url': archive_path},
 ])
- already_installed = [('bacon', '0.1', []), 
- ('chicken', '1.1', ['bacon (0.1)'])] 
- output = get_install_info("choxie", index=client, already_installed= 
- get_fake_dists(already_installed))
- 
+ already_installed = [('bacon', '0.1', []),
+ ('chicken', '1.1', ['bacon (0.1)'])]
+ output = get_infos("choxie", index=client, installed=
+ get_fake_dists(already_installed))
+
 # we need bacon 0.2, but 0.1 is installed.
 # So we expect to remove 0.1 and to install 0.2 instead.
- installed = [(o.name, '%s' % o.version) for o in output['install']]
- remove = [(o.name, '%s' % o.version) for o in output['remove']]
- conflict = [(o.name, '%s' % o.version) for o in output['conflict']]
+ installed, remove, conflict = self._get_results(output)
 self.assertIn(('choxie', '2.0.0.9'), installed)
 self.assertIn(('towel-stuff', '0.1'), installed)
 self.assertIn(('bacon', '0.2'), installed)
@@ -139,7 +147,7 @@
 # Test that the isntalled raises an exception if the project does not
 # exists.
 client = self._get_client(server)
- self.assertRaises(InstallationException, get_install_info, 
+ self.assertRaises(InstallationException, get_infos,
 'unexistant project', index=client)
 
 
--
Repository URL: http://hg.python.org/distutils2


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /