diff options
| author | Alexis Metaireau <alexis@notmyidea.org> | 2011-01-29 16:37:11 +0100 |
|---|---|---|
| committer | Alexis Metaireau <alexis@notmyidea.org> | 2011-01-29 16:37:11 +0100 |
| commit | 245f5aa21d864759fab465e669151ec601be2efc (patch) | |
| tree | bfdd90990cfd196e0813f2e6cd5a646adafc3d7e /distutils2 | |
| parent | 30ba971c0d781317724ca1afc75344f5b0ceaeb4 (diff) | |
| download | disutils2-245f5aa21d864759fab465e669151ec601be2efc.tar.gz | |
Update installer tests.
Diffstat (limited to 'distutils2')
| -rw-r--r-- | distutils2/index/xmlrpc.py | 2 | ||||
| -rw-r--r-- | distutils2/install.py | 20 | ||||
| -rw-r--r-- | distutils2/tests/pypi_server.py | 1 | ||||
| -rw-r--r-- | distutils2/tests/test_install.py | 176 |
4 files changed, 138 insertions, 61 deletions
diff --git a/distutils2/index/xmlrpc.py b/distutils2/index/xmlrpc.py index ea688b7..54d7367 100644 --- a/distutils2/index/xmlrpc.py +++ b/distutils2/index/xmlrpc.py @@ -131,7 +131,7 @@ class Client(BaseClient): Return a ReleaseInfo object, with metadata informations filled in. """ - # to be case-insensitive + # to be case-insensitive, get the informations from the XMLRPC API projects = [d['name'] for d in self.proxy.search({'name': project_name}) if d['name'].lower() == project_name] diff --git a/distutils2/install.py b/distutils2/install.py index 228767e..2a1574f 100644 --- a/distutils2/install.py +++ b/distutils2/install.py @@ -139,7 +139,7 @@ def install_dists(dists, path=None): # reverting for d in installed_dists: - _uninstall(d) + uninstall(d) raise e return installed_files @@ -226,8 +226,6 @@ def get_infos(requirements, index=None, installed=None, prefer_final=True): Conflict contains all the conflicting distributions, if there is a conflict. """ - from ipdb import set_trace - set_trace() if not installed: logger.info('Reading installed distributions') installed = get_distributions(use_egg_info=True) @@ -237,16 +235,20 @@ def get_infos(requirements, index=None, installed=None, prefer_final=True): predicate = get_version_predicate(requirements) found = False installed = list(installed) + + # check that the project isnt already installed for installed_project in installed: # is it a compatible project ? if predicate.name.lower() != installed_project.name.lower(): continue found = True logger.info('Found %s %s' % (installed_project.name, - installed_project.metadata.version)) - if predicate.match(installed_project.metadata.version): - return infos + installed_project.version)) + # if we already have something installed, check it matches the + # requirements + if predicate.match(installed_project.version): + return infos break if not found: @@ -260,7 +262,7 @@ def get_infos(requirements, index=None, installed=None, prefer_final=True): releases = index.get_releases(requirements) except (ReleaseNotFound, ProjectNotFound), e: raise InstallationException('Release not found: "%s"' % requirements) - + # Pick up a release, and try to get the dependency tree release = releases.get_last(requirements, prefer_final=prefer_final) @@ -284,7 +286,7 @@ def get_infos(requirements, index=None, installed=None, prefer_final=True): # Get what the missing deps are dists = depgraph.missing[release] if dists: - logger.info("missing dependencies found, installing them") + logger.info("missing dependencies found, retrieving metadata") # we have missing deps for dist in dists: _update_infos(infos, get_infos(dist, index, installed)) @@ -333,7 +335,7 @@ def install(project): install_path=install_path) except InstallationConflict, e: - projects = ['%s %s' % (p.name, p.metadata.version) for p in e.args[0]] + projects = ['%s %s' % (p.name, p.version) for p in e.args[0]] logger.info('"%s" conflicts with "%s"' % (project, ','.join(projects))) diff --git a/distutils2/tests/pypi_server.py b/distutils2/tests/pypi_server.py index 0dc0f6d..063e726 100644 --- a/distutils2/tests/pypi_server.py +++ b/distutils2/tests/pypi_server.py @@ -375,6 +375,7 @@ class XMLRPCMockIndex(object): def __init__(self, dists=[]): self._dists = dists + self._search_result = [] def add_distributions(self, dists): for dist in dists: diff --git a/distutils2/tests/test_install.py b/distutils2/tests/test_install.py index 2e95ba8..67c61c2 100644 --- a/distutils2/tests/test_install.py +++ b/distutils2/tests/test_install.py @@ -29,27 +29,16 @@ class InstalledDist(object): class ToInstallDist(object): """Distribution that will be installed""" - def __init__(self, raise_error=False, files=False): - self._raise_error = raise_error + def __init__(self, files=False): self._files = files - self.install_called = False - self.install_called_with = {} self.uninstall_called = False self._real_files = [] + self.name = "fake" + self.version = "fake" if files: for f in range(0,3): self._real_files.append(mkstemp()) - def install(self, *args): - self.install_called = True - self.install_called_with = args - if self._raise_error: - raise Exception('Oops !') - return ['/path/to/foo', '/path/to/bar'] - - def uninstall(self, **args): - self.uninstall_called = True - def get_installed_files(self, **args): if self._files: return [f[1] for f in self._real_files] @@ -58,7 +47,49 @@ class ToInstallDist(object): return self.get_installed_files() +class MagicMock(object): + def __init__(self, return_value=None, raise_exception=False): + self.called = False + self._times_called = 0 + self._called_with = [] + self._return_value = return_value + self._raise = raise_exception + + def __call__(self, *args, **kwargs): + self.called = True + self._times_called = self._times_called + 1 + self._called_with.append((args, kwargs)) + iterable = hasattr(self._raise, '__iter__') + if self._raise: + if ((not iterable and self._raise) + or self._raise[self._times_called - 1]): + raise Exception + return self._return_value + + def called_with(self, *args, **kwargs): + return (args, kwargs) in self._called_with + + +def patch(parent, to_patch): + """monkey match a module""" + def wrapper(func): + print func + print dir(func) + old_func = getattr(parent, to_patch) + def wrapped(*args, **kwargs): + parent.__dict__[to_patch] = MagicMock() + try: + out = func(*args, **kwargs) + finally: + setattr(parent, to_patch, old_func) + return out + return wrapped + return wrapper + + def get_installed_dists(dists): + """Return a list of fake installed dists. + The list is name, version, deps""" objects = [] for (name, version, deps) in dists: objects.append(InstalledDist(name, version, deps)) @@ -69,6 +100,12 @@ class TestInstall(TempdirManager, unittest.TestCase): def _get_client(self, server, *args, **kwargs): return Client(server.full_address, *args, **kwargs) + def _patch_run_install(self): + """Patch run install""" + + def _unpatch_run_install(self): + """Unpatch run install for d2 and d1""" + def _get_results(self, output): """return a list of results""" installed = [(o.name, '%s' % o.version) for o in output['install']] @@ -150,6 +187,8 @@ class TestInstall(TempdirManager, unittest.TestCase): # Tests that conflicts are detected client = self._get_client(server) archive_path = '%s/distribution.tar.gz' % server.full_address + + # choxie depends on towel-stuff, which depends on bacon. server.xmlrpc.set_distributions([ {'name':'choxie', 'version': '2.0.0.9', @@ -164,7 +203,9 @@ class TestInstall(TempdirManager, unittest.TestCase): 'requires_dist': [], 'url': archive_path}, ]) - already_installed = [('bacon', '0.1', []), + + # name, version, deps. + already_installed = [('bacon', '0.1', []), ('chicken', '1.1', ['bacon (0.1)'])] output = install.get_infos("choxie", index=client, installed= get_installed_dists(already_installed)) @@ -221,23 +262,39 @@ class TestInstall(TempdirManager, unittest.TestCase): # if one of the distribution installation fails, call uninstall on all # installed distributions. - d1 = ToInstallDist() - d2 = ToInstallDist(raise_error=True) - self.assertRaises(Exception, install.install_dists, [d1, d2]) - for dist in (d1, d2): - self.assertTrue(dist.install_called) - self.assertTrue(d1.uninstall_called) - self.assertFalse(d2.uninstall_called) + old_install_dist = install._install_dist + old_uninstall = getattr(install, 'uninstall', None) + + install._install_dist = MagicMock(return_value=[], + raise_exception=(False, True)) + install.uninstall = MagicMock() + try: + d1 = ToInstallDist() + d2 = ToInstallDist() + path = self.mkdtemp() + self.assertRaises(Exception, install.install_dists, [d1, d2], path) + self.assertTrue(install._install_dist.called_with(d1, path)) + self.assertTrue(install.uninstall.called) + finally: + install._install_dist = old_install_dist + install.uninstall = old_uninstall + def test_install_dists_success(self): - # test that the install method is called on each of the distributions. - d1 = ToInstallDist() - d2 = ToInstallDist() - install.install_dists([d1, d2]) - for dist in (d1, d2): - self.assertTrue(dist.install_called) - self.assertFalse(d1.uninstall_called) - self.assertFalse(d2.uninstall_called) + old_install_dist = install._install_dist + install._install_dist = MagicMock(return_value=[]) + try: + # test that the install method is called on each of the distributions. + d1 = ToInstallDist() + d2 = ToInstallDist() + + # should call install + path = self.mkdtemp() + install.install_dists([d1, d2], path) + for dist in (d1, d2): + self.assertTrue(install._install_dist.called_with(dist, path)) + finally: + install._install_dist = old_install_dist def test_install_from_infos_conflict(self): # assert conflicts raise an exception @@ -262,29 +319,46 @@ class TestInstall(TempdirManager, unittest.TestCase): install.install_dists = old_install_dists def test_install_from_infos_remove_rollback(self): - # assert that if an error occurs, the removed files are restored. - remove = [] - for i in range(0,2): - remove.append(ToInstallDist(files=True, raise_error=True)) - to_install = [ToInstallDist(raise_error=True), - ToInstallDist()] - - install.install_from_infos(remove=remove, install=to_install) - # assert that the files are in the same place - # assert that the files have been removed - for dist in remove: - for f in dist.get_installed_files(): - self.assertTrue(os.path.exists(f)) + old_install_dist = install._install_dist + old_uninstall = getattr(install, 'uninstall', None) + + install._install_dist = MagicMock(return_value=[], + raise_exception=(False, True)) + install.uninstall = MagicMock() + try: + # assert that if an error occurs, the removed files are restored. + remove = [] + for i in range(0,2): + remove.append(ToInstallDist(files=True)) + to_install = [ToInstallDist(), ToInstallDist()] + + self.assertRaises(Exception, install.install_from_infos, + remove=remove, install=to_install) + # assert that the files are in the same place + # assert that the files have been removed + for dist in remove: + for f in dist.get_installed_files(): + self.assertTrue(os.path.exists(f)) + finally: + install.install_dist = old_install_dist + install.uninstall = old_uninstall + def test_install_from_infos_install_succes(self): - # assert that the distribution can be installed - install_path = "my_install_path" - to_install = [ToInstallDist(), ToInstallDist()] - - install.install_from_infos(install=to_install, - install_path=install_path) - for dist in to_install: - self.assertEqual(dist.install_called_with, (install_path,)) + old_install_dist = install._install_dist + install._install_dist = MagicMock([]) + try: + # assert that the distribution can be installed + install_path = "my_install_path" + to_install = [ToInstallDist(), ToInstallDist()] + + install.install_from_infos(install=to_install, + install_path=install_path) + for dist in to_install: + install._install_dist.called_with(install_path) + finally: + install._install_dist = old_install_dist + def test_suite(): suite = unittest.TestSuite() |
