def test_graph_bad_version_to_dot(self): expected = ( ('towel-stuff', 'bacon', 'bacon (<=0.2)'), ('grammar', 'bacon', 'truffles (>=1.2)'), ('choxie', 'towel-stuff', 'towel-stuff (0.1)'), ('banana', 'strawberry', 'strawberry (>=0.5)'), ) dists = self.get_dists( self.DISTROS_DIST + self.DISTROS_EGG + self.BAD_EGGS, True) graph = make_graph(dists) buf = StringIO() graph.to_dot(buf) buf.seek(0) matches = [] lines = buf.readlines() for line in lines[1:-1]: # skip the first and the last lines if line[-1] == '\n': line = line[:-1] match = self.EDGE.match(line.strip()) self.assertIsNot(match, None) matches.append(match.groups()) self.checkLists(matches, expected)
def test_dependency_finder(self): locator = AggregatingLocator( JSONLocator(), SimpleScrapingLocator('https://pypi.python.org/simple/', timeout=3.0), scheme='legacy') finder = DependencyFinder(locator) dists, problems = finder.find('irc (== 5.0.1)') self.assertFalse(problems) actual = sorted([d.name for d in dists]) self.assertEqual(actual, ['hgtools', 'irc', 'pytest-runner']) dists, problems = finder.find('irc (== 5.0.1)', meta_extras=[':test:']) self.assertFalse(problems) actual = sorted([d.name for d in dists]) self.assertEqual(actual, ['hgtools', 'irc', 'py', 'pytest', 'pytest-runner']) g = make_graph(dists) slist, cycle = g.topological_sort() self.assertFalse(cycle) names = [d.name for d in slist] expected = set([ ('hgtools', 'py', 'pytest', 'pytest-runner', 'irc'), ('py', 'hgtools', 'pytest', 'pytest-runner', 'irc'), ('hgtools', 'py', 'pytest-runner', 'pytest', 'irc'), ('py', 'hgtools', 'pytest-runner', 'pytest', 'irc') ]) self.assertIn(tuple(names), expected) # Test with extras dists, problems = finder.find('Jinja2 (== 2.6)') self.assertFalse(problems) actual = sorted([d.name_and_version for d in dists]) self.assertEqual(actual, ['Jinja2 (2.6)']) dists, problems = finder.find('Jinja2 [i18n] (== 2.6)') self.assertFalse(problems) actual = sorted([d.name_and_version for d in dists]) self.assertEqual(actual[-2], 'Jinja2 (2.6)') self.assertTrue(actual[-1].startswith('pytz (')) self.assertTrue(actual[0].startswith('Babel (')) actual = [d.build_time_dependency for d in dists] self.assertEqual(actual, [False, False, False]) # Now test with extra in dependency locator.clear_cache() dummy = make_dist('dummy', '0.1') dummy.metadata.run_requires = [{'requires': ['Jinja2 [i18n]']}] dists, problems = finder.find(dummy) self.assertFalse(problems) actual = sorted([d.name_and_version for d in dists]) self.assertTrue(actual[0].startswith('Babel (')) locator.clear_cache() dummy.metadata.run_requires = [{'requires': ['Jinja2']}] dists, problems = finder.find(dummy) self.assertFalse(problems) actual = sorted([d.name_and_version for d in dists]) self.assertTrue(actual[0].startswith('Jinja2 ('))
def test_graph_bad_version_to_dot(self): expected = ( ('towel-stuff', 'bacon', 'bacon (<=0.2)'), ('grammar', 'bacon', 'truffles (>=1.2)'), ('choxie', 'towel-stuff', 'towel-stuff (0.1)'), ('banana', 'strawberry', 'strawberry (>=0.5)'), ) dists = self.get_dists(self.DISTROS_DIST + self.DISTROS_EGG + self.BAD_EGGS, True) graph = make_graph(dists) buf = StringIO() graph.to_dot(buf) buf.seek(0) matches = [] lines = buf.readlines() for line in lines[1:-1]: # skip the first and the last lines if line[-1] == '\n': line = line[:-1] match = self.EDGE.match(line.strip()) self.assertIsNot(match, None) matches.append(match.groups()) self.checkLists(matches, expected)
def test_graph_disconnected_to_dot(self): dependencies_expected = ( ('towel-stuff', 'bacon', 'bacon (<=0.2)'), ('grammar', 'bacon', 'truffles (>=1.2)'), ('choxie', 'towel-stuff', 'towel-stuff (0.1)'), ('banana', 'strawberry', 'strawberry (>=0.5)'), ) disconnected_expected = ('cheese', 'bacon', 'strawberry') dists = self.get_dists(self.DISTROS_DIST + self.DISTROS_EGG, True) graph = make_graph(dists) buf = StringIO() graph.to_dot(buf, skip_disconnected=False) buf.seek(0) lines = buf.readlines() dependencies_lines = [] disconnected_lines = [] # First sort output lines into dependencies and disconnected lines. # We also skip the attribute lines, and don't include the "{" and "}" # lines. disconnected_active = False for line in lines[1:-1]: # Skip first and last line if line.startswith('subgraph disconnected'): disconnected_active = True continue if line.startswith('}') and disconnected_active: disconnected_active = False continue if disconnected_active: # Skip the 'label = "Disconnected"', etc. attribute lines. if ' = ' not in line: disconnected_lines.append(line) else: dependencies_lines.append(line) dependencies_matches = [] for line in dependencies_lines: if line[-1] == '\n': line = line[:-1] match = self.EDGE.match(line.strip()) self.assertIsNot(match, None) dependencies_matches.append(match.groups()) disconnected_matches = [] for line in disconnected_lines: if line[-1] == '\n': line = line[:-1] line = line.strip('"') disconnected_matches.append(line) self.checkLists(dependencies_matches, dependencies_expected) self.checkLists(disconnected_matches, disconnected_expected)
def test_graph_disconnected_to_dot(self): dependencies_expected = ( ('towel-stuff', 'bacon', 'bacon (<=0.2)'), ('grammar', 'bacon', 'truffles (>=1.2)'), ('choxie', 'towel-stuff', 'towel-stuff (0.1)'), ('banana', 'strawberry', 'strawberry (>=0.5)'), ) disconnected_expected = ('cheese', 'bacon', 'strawberry') dists = self.get_dists(self.DISTROS_DIST + self.DISTROS_EGG, True) graph = make_graph(dists) buf = StringIO() graph.to_dot(buf, skip_disconnected=False) buf.seek(0) lines = buf.readlines() dependencies_lines = [] disconnected_lines = [] # First sort output lines into dependencies and disconnected lines. # We also skip the attribute lines, and don't include the "{" and "}" # lines. disconnected_active = False for line in lines[1:-1]: # Skip first and last line if line.startswith('subgraph disconnected'): disconnected_active = True continue if line.startswith('}') and disconnected_active: disconnected_active = False continue if disconnected_active: # Skip the 'label = "Disconnected"', etc. attribute lines. if ' = ' not in line: disconnected_lines.append(line) else: dependencies_lines.append(line) dependencies_matches = [] for line in dependencies_lines: if line[-1] == '\n': line = line[:-1] match = self.EDGE.match(line.strip()) self.assertIsNot(match, None) dependencies_matches.append(match.groups()) disconnected_matches = [] for line in disconnected_lines: if line[-1] == '\n': line = line[:-1] line = line.strip('"') disconnected_matches.append(line) self.checkLists(dependencies_matches, dependencies_expected) self.checkLists(disconnected_matches, disconnected_expected)
def _install_check_incompatible(need): all = dict([ (d.name, d) for d in installed_core() | installed_tools() | installed_toolboxes() ]) all.update([ (d.name, d) for d in need ]) from distlib.database import make_graph graph = make_graph(all.values()) if graph.missing: for d, req_list in graph.missing: if len(req_list) == 1: s = repr(req_list[0]) else: s = " and ".join(", ".join([ repr(r) for r in req_list[:-1] ]), repr(req_list[-1])) show("Warning: \"%s\" needs %s" % (d.name, s)) return True else: return False
def _installed_init(): global _inst_chimera_core, _inst_core, _inst_tools, _inst_toolboxes # Filter the distribution list to get around # bug where some installations have bad metadata all_distributions = [] for d in installed_path().get_distributions(): try: d.run_requires except: continue else: all_distributions.append(d) # Find only the Chimera distribution packages l = installed_locator() core = l.locate(_ChimeraCore) if core is None: _inst_core = set() _inst_tools = set() _inst_toolboxes = set() #raise RuntimeError("cannot find distribution \"%s\"" % _ChimeraCore) DEBUG("warning: \"%s\" distribution not found" % _ChimeraCore) return from distlib.database import make_graph dg = make_graph(all_distributions) known_dists = set([ core ]) _inst_chimera_core = core _inst_core = set([core]) _inst_tools = set() _inst_toolboxes = set() for d, label in dg.adjacency_list[core]: _inst_core.add(d) check_list = [ core ] while check_list: for d in dg.reverse_list[check_list.pop()]: if d in known_dists: continue known_dists.add(d) check_list.append(d) name = d.name if name == _ChimeraTools or name == _ChimeraToolboxes: continue if name.startswith(_ChimeraToolboxPrefix): _inst_toolboxes.add(d) else: _inst_tools.add(d)
def test_make_graph(self): dists = self.get_dists(self.DISTROS_DIST) choxie, grammar, towel = dists graph = make_graph(dists) deps = [(x.name, y) for x, y in graph.adjacency_list[choxie]] self.checkLists([('towel-stuff', 'towel-stuff (0.1)')], deps) self.assertIn(choxie, graph.reverse_list[towel]) self.checkLists(graph.missing[choxie], ['nut']) deps = [(x.name, y) for x, y in graph.adjacency_list[grammar]] self.checkLists([], deps) self.checkLists(graph.missing[grammar], ['truffles (>=1.2)']) deps = [(x.name, y) for x, y in graph.adjacency_list[towel]] self.checkLists([], deps) self.checkLists(graph.missing[towel], ['bacon (<=0.2)'])
def test_make_graph(self): dists = self.get_dists(self.DISTROS_DIST) choxie, grammar, towel = dists graph = make_graph(dists) deps = [(x.name, y) for x, y in graph.adjacency_list[choxie]] self.checkLists([('towel-stuff', 'towel-stuff (0.1)')], deps) self.assertIn(choxie, graph.reverse_list[towel]) self.checkLists(graph.missing[choxie], ['nut']) deps = [(x.name, y) for x, y in graph.adjacency_list[grammar]] self.checkLists([], deps) self.checkLists(graph.missing[grammar], ['truffles (>=1.2)']) deps = [(x.name, y) for x, y in graph.adjacency_list[towel]] self.checkLists([], deps) self.checkLists(graph.missing[towel], ['bacon (<=0.2)'])
def test_make_graph_egg(self): dists = self.get_dists(self.DISTROS_DIST + self.DISTROS_EGG, True) choxie, grammar, towel, bacon, banana, strawberry, cheese = dists graph = make_graph(dists) deps = [(x.name, y) for x, y in graph.adjacency_list[choxie]] self.checkLists([('towel-stuff', 'towel-stuff (0.1)')], deps) self.assertIn(choxie, graph.reverse_list[towel]) self.checkLists(graph.missing[choxie], ['nut']) deps = [(x.name, y) for x, y in graph.adjacency_list[grammar]] self.checkLists([('bacon', 'truffles (>=1.2)')], deps) self.checkLists(graph.missing.get(grammar, []), []) self.assertIn(grammar, graph.reverse_list[bacon]) deps = [(x.name, y) for x, y in graph.adjacency_list[towel]] self.checkLists([('bacon', 'bacon (<=0.2)')], deps) self.checkLists(graph.missing.get(towel, []), []) self.assertIn(towel, graph.reverse_list[bacon]) deps = [(x.name, y) for x, y in graph.adjacency_list[bacon]] self.checkLists([], deps) self.checkLists(graph.missing.get(bacon, []), []) deps = [(x.name, y) for x, y in graph.adjacency_list[banana]] self.checkLists([('strawberry', 'strawberry (>=0.5)')], deps) self.checkLists(graph.missing.get(banana, []), []) self.assertIn(banana, graph.reverse_list[strawberry]) deps = [(x.name, y) for x, y in graph.adjacency_list[strawberry]] self.checkLists([], deps) self.checkLists(graph.missing.get(strawberry, []), []) deps = [(x.name, y) for x, y in graph.adjacency_list[cheese]] self.checkLists([], deps) self.checkLists(graph.missing.get(cheese, []), [])
def test_make_graph_egg(self): dists = self.get_dists(self.DISTROS_DIST + self.DISTROS_EGG, True) choxie, grammar, towel, bacon, banana, strawberry, cheese = dists graph = make_graph(dists) deps = [(x.name, y) for x, y in graph.adjacency_list[choxie]] self.checkLists([('towel-stuff', 'towel-stuff (0.1)')], deps) self.assertIn(choxie, graph.reverse_list[towel]) self.checkLists(graph.missing[choxie], ['nut']) deps = [(x.name, y) for x, y in graph.adjacency_list[grammar]] self.checkLists([('bacon', 'truffles (>=1.2)')], deps) self.checkLists(graph.missing.get(grammar, []), []) self.assertIn(grammar, graph.reverse_list[bacon]) deps = [(x.name, y) for x, y in graph.adjacency_list[towel]] self.checkLists([('bacon', 'bacon (<=0.2)')], deps) self.checkLists(graph.missing.get(towel, []), []) self.assertIn(towel, graph.reverse_list[bacon]) deps = [(x.name, y) for x, y in graph.adjacency_list[bacon]] self.checkLists([], deps) self.checkLists(graph.missing.get(bacon, []), []) deps = [(x.name, y) for x, y in graph.adjacency_list[banana]] self.checkLists([('strawberry', 'strawberry (>=0.5)')], deps) self.checkLists(graph.missing.get(banana, []), []) self.assertIn(banana, graph.reverse_list[strawberry]) deps = [(x.name, y) for x, y in graph.adjacency_list[strawberry]] self.checkLists([], deps) self.checkLists(graph.missing.get(strawberry, []), []) deps = [(x.name, y) for x, y in graph.adjacency_list[cheese]] self.checkLists([], deps) self.checkLists(graph.missing.get(cheese, []), [])
def test_graph_to_dot(self): expected = ( ("towel-stuff", "bacon", "bacon (<=0.2)"), ("grammar", "bacon", "truffles (>=1.2)"), ("choxie", "towel-stuff", "towel-stuff (0.1)"), ("banana", "strawberry", "strawberry (>=0.5)"), ) dists = self.get_dists(self.DISTROS_DIST + self.DISTROS_EGG, True) graph = make_graph(dists) buf = StringIO() graph.to_dot(buf) buf.seek(0) matches = [] lines = buf.readlines() for line in lines[1:-1]: # skip the first and the last lines if line[-1] == "\n": line = line[:-1] match = self.EDGE.match(line.strip()) self.assertIsNot(match, None) matches.append(match.groups()) self.checkLists(matches, expected)
def test_dependency_finder(self): locator = AggregatingLocator( JSONLocator(), SimpleScrapingLocator("https://pypi.python.org/simple/", timeout=3.0), scheme="legacy" ) finder = DependencyFinder(locator) dists, problems = finder.find("irc (== 5.0.1)") self.assertFalse(problems) actual = sorted([d.name for d in dists]) self.assertEqual(actual, ["hgtools", "irc", "pytest-runner", "setuptools_scm"]) dists, problems = finder.find("irc (== 5.0.1)", meta_extras=[":test:"]) self.assertFalse(problems) actual = sorted([d.name for d in dists]) self.assertEqual(actual, ["hgtools", "irc", "py", "pytest", "pytest-runner", "setuptools_scm"]) g = make_graph(dists) slist, cycle = g.topological_sort() self.assertFalse(cycle) names = [d.name for d in slist] expected = set( [ ("setuptools_scm", "hgtools", "py", "pytest-runner", "pytest", "irc"), ("setuptools_scm", "hgtools", "py", "pytest", "pytest-runner", "irc"), ("setuptools_scm", "py", "hgtools", "pytest-runner", "pytest", "irc"), ("hgtools", "setuptools_scm", "py", "pytest", "pytest-runner", "irc"), ("py", "hgtools", "setuptools_scm", "pytest", "pytest-runner", "irc"), ("hgtools", "setuptools_scm", "py", "pytest-runner", "pytest", "irc"), ("py", "hgtools", "setuptools_scm", "pytest-runner", "pytest", "irc"), ("py", "setuptools_scm", "hgtools", "pytest", "pytest-runner", "irc"), ("pytest", "setuptools_scm", "hgtools", "pytest-runner", "irc"), ("hgtools", "setuptools_scm", "pytest", "pytest-runner", "irc"), ("py", "setuptools_scm", "hgtools", "pytest-runner", "pytest", "irc"), ("py", "setuptools_scm", "pytest", "pytest-runner", "hgtools", "irc"), ("py", "setuptools_scm", "pytest-runner", "pytest", "hgtools", "irc"), ("py", "setuptools_scm", "pytest", "hgtools", "pytest-runner", "irc"), ("setuptools_scm", "py", "pytest", "hgtools", "pytest-runner", "irc"), ("setuptools_scm", "py", "pytest-runner", "hgtools", "pytest", "irc"), ("py", "setuptools_scm", "pytest-runner", "hgtools", "pytest", "irc"), ("setuptools_scm", "py", "pytest", "pytest-runner", "hgtools", "irc"), ] ) self.assertIn(tuple(names), expected) # Test with extras dists, problems = finder.find("Jinja2 (== 2.6)") self.assertFalse(problems) actual = sorted([d.name_and_version for d in dists]) self.assertEqual(actual, ["Jinja2 (2.6)"]) dists, problems = finder.find("Jinja2 [i18n] (== 2.6)") self.assertFalse(problems) actual = sorted([d.name_and_version for d in dists]) self.assertEqual(actual[-2], "Jinja2 (2.6)") self.assertTrue(actual[-1].startswith("pytz (")) self.assertTrue(actual[0].startswith("Babel (")) actual = [d.build_time_dependency for d in dists] self.assertEqual(actual, [False, False, False]) # Now test with extra in dependency locator.clear_cache() dummy = make_dist("dummy", "0.1") dummy.metadata.run_requires = [{"requires": ["Jinja2 [i18n]"]}] dists, problems = finder.find(dummy) self.assertFalse(problems) actual = sorted([d.name_and_version for d in dists]) self.assertTrue(actual[0].startswith("Babel (")) locator.clear_cache() dummy.metadata.run_requires = [{"requires": ["Jinja2"]}] dists, problems = finder.find(dummy) self.assertFalse(problems) actual = sorted([d.name_and_version for d in dists]) self.assertTrue(actual[0].startswith("Jinja2 ("))
def uninstall(names=None, always=False, unused=True): """Remove packages. ''names'' is a list of package names of interest, including version specifications as specified in PEP 426. ''always'' is a boolean indicating whether update should proceed if it would result in packages with unsatisfied dependencies.""" if names is None: raise RuntimeError("no distribution specified for removal") remove_set = set() l = installed_locator() for name in names: d = l.locate(name) if d is None: show("Error: distribution \"%s\" not found" % name) raise RuntimeError("Distribution \"%s\" not found" % name) remove_set.add(d) from distlib.database import make_graph all = installed_core() | installed_tools() | installed_toolboxes() graph = make_graph(all) stranded = set() for d in remove_set: for pd in graph.reverse_list[d]: if pd not in remove_set: # Bad case. pd _will not_ be removed but # is depending on d which _will_ be removed stranded.add(pd) if stranded: msg = ("following distributions will have missing requirements: %s" % ", ".join([ d.name for d in stranded ])) if not always: raise RuntimeError(msg) else: show("Warning:", msg) if unused: added = True while added: added = False for d in all: if d in remove_set: # already scheduled for removal # leave it alone continue rl = graph.reverse_list[d] if not rl: # not referenced at all # leave it alone continue for rd in rl: if rd not in remove_set: # used by not-removed distribution # leave it alone break else: # only referred to by removed distributions # get rid of this one too remove_set.add(d) import sys added = True for d in remove_set: _remove_distribution(d) reset(repo=False)
def test_repr(self): dists = self.get_dists(self.DISTROS_DIST + self.DISTROS_EGG + self.BAD_EGGS, True) graph = make_graph(dists) self.assertTrue(repr(graph))
def _install_wheels(need, system): # TODO: if a package is being updated, it should be installed in # the same location as before # Find all packages that should be deleted all = dict([ (d.name, d) for d in installed_core() | installed_tools() | installed_toolboxes() ]) from distlib.database import make_graph import itertools graph = make_graph(itertools.chain(all.values(), need)) l = need[:] # what we started with ordered = [] # ordered by least dependency depend = {} # dependency relationship cache while l: for d in l: for d2 in l: if d2 is d: continue try: dep = depend[(d, d2)] except KeyError: dep = _depends_on(graph, d, d2) depend[(d, d2)] = dep if dep: break else: ordered.append(d) l.remove(d) break else: # This can only happen if there is circular dependencies # in which case we just process the distributions in # given order since its no worse than anything else ordered.extend(l) break remove_list = [] check = set() for d in ordered: if d in remove_list: continue try: rd = all[d.name] except KeyError: pass else: remove_list.append(rd) al = graph.adjacency_list[rd] if al: check.update([ sd for sd, l in al ]) # Repeatedly go through the list of distributions to see whether # they can be removed. It must be iterative. Suppose A and B need # to be removed; C depends on A; D depends on B and C; if we check D # first, it will not be removable since C is not marked for removal # yet; but a second pass will show that D is removable. Iteration # ends when no new packages are marked as removable. while check: any_deletion = False new_check = set() for d in check: for pd in graph.reverse_list[d]: if pd not in remove_list: new_check.add(d) break else: any_deletion = True remove_list.append(d) for sd, l in graph.adjacency_list[d]: if sd not in remove_list and sd not in check: new_check.add(sd) if not any_deletion: break check = new_check removed_location = {} for d in remove_list: removed_location[d.name] = _remove_distribution(d) dl = download_location() default_paths = _install_make_paths(system) from distlib.scripts import ScriptMaker maker = ScriptMaker(None, None) import os.path try: from urllib.request import urlretrieve, URLError except ImportError: from urllib import urlretrieve, URLError from distlib.wheel import Wheel from distlib import DistlibException for d in need: try: old_location = removed_location[d.name] except KeyError: paths = default_paths else: paths = _install_make_paths(system, old_location) url = d.source_url filename = url.split('/')[-1] dloc = os.path.join(dl, filename) if not os.path.isfile(dloc): try: filename, headers = urlretrieve(url, dloc) except URLError as e: show("Warning: cannot fetch %s: %s" % (url, str(e))) continue w = Wheel(dloc) try: w.verify() except DistlibExecption as e: show("Warning: cannot verify %s: %s" % (d.name, str(e))) continue show("installing %s (%s)" % (w.name, w.version)) w.install(paths, maker)
def test_repr(self): dists = self.get_dists( self.DISTROS_DIST + self.DISTROS_EGG + self.BAD_EGGS, True) graph = make_graph(dists) self.assertTrue(repr(graph))
#!/usr/bin/env python from distlib.database import DistributionPath dist_path = DistributionPath() mylist = list(dist_path.get_distributions()) from distlib.database import make_graph print(make_graph(mylist))
def main(args=None): parser = optparse.OptionParser(usage='%prog [options] requirement [requirement ...]') parser.add_option('-d', '--dest', dest='destdir', metavar='DESTDIR', default=os.getcwd(), help='Where you want the wheels ' 'to be put.') parser.add_option('-n', '--no-deps', dest='deps', default=True, action='store_false', help='Don\'t build dependent wheels.') options, args = parser.parse_args(args) options.compatible = True # may add flag to turn off later if not args: parser.print_usage() else: # Check if pip is available; no point in continuing, otherwise try: with open(os.devnull, 'w') as f: p = subprocess.call(['pip', '--version'], stdout=f, stderr=subprocess.STDOUT) except Exception: p = 1 if p: print('pip appears not to be available. Wheeler needs pip to ' 'build wheels.') return 1 if options.deps: # collect all the requirements, including dependencies u = 'http://pypi.python.org/simple/' locator = AggregatingLocator(JSONLocator(), SimpleScrapingLocator(u, timeout=3.0), scheme='legacy') finder = DependencyFinder(locator) wanted = set() for arg in args: r = parse_requirement(arg) if not r.constraints: dname = r.name else: dname = '%s (%s)' % (r.name, ', '.join(r.constraints)) print('Finding the dependencies of %s ...' % arg) dists, problems = finder.find(dname) if problems: print('There were some problems resolving dependencies ' 'for %r.' % arg) for _, info in problems: print(' Unsatisfied requirement %r' % info) wanted |= dists want_ordered = True # set to False to skip ordering if not want_ordered: wanted = list(wanted) else: graph = make_graph(wanted, scheme=locator.scheme) slist, cycle = graph.topological_sort() if cycle: # Now sort the remainder on dependency count. cycle = sorted(cycle, reverse=True, key=lambda d: len(graph.reverse_list[d])) wanted = slist + cycle # get rid of any installed distributions from the list for w in list(wanted): dist = INSTALLED_DISTS.get_distribution(w.name) if dist or w.name in ('setuptools', 'distribute'): wanted.remove(w) s = w.name_and_version print('Skipped already-installed distribution %s' % s) # converted wanted list to pip-style requirements args = ['%s==%s' % (dist.name, dist.version) for dist in wanted] # Now go build built = [] for arg in args: wheel = build_wheel(arg, options) if wheel: built.append(wheel) if built: if options.destdir == os.getcwd(): dest = '' else: dest = ' in %s' % options.destdir print('The following wheels were built%s:' % dest) for wheel in built: print(' %s' % wheel.filename)
def test_dependency_finder(self): locator = AggregatingLocator(JSONLocator(), SimpleScrapingLocator( 'https://pypi.python.org/simple/', timeout=3.0), scheme='legacy') finder = DependencyFinder(locator) dists, problems = finder.find('irc (== 5.0.1)') self.assertFalse(problems) actual = sorted([d.name for d in dists]) self.assertEqual(actual, ['hgtools', 'irc', 'pytest-runner', 'setuptools_scm']) dists, problems = finder.find('irc (== 5.0.1)', meta_extras=[':test:']) self.assertFalse(problems) actual = sorted([d.name for d in dists]) self.assertEqual(actual, [ 'hgtools', 'irc', 'py', 'pytest', 'pytest-runner', 'setuptools_scm' ]) g = make_graph(dists) slist, cycle = g.topological_sort() self.assertFalse(cycle) names = [d.name for d in slist] expected = set([ ('setuptools_scm', 'hgtools', 'py', 'pytest-runner', 'pytest', 'irc'), ('setuptools_scm', 'hgtools', 'py', 'pytest', 'pytest-runner', 'irc'), ('setuptools_scm', 'py', 'hgtools', 'pytest-runner', 'pytest', 'irc'), ('hgtools', 'setuptools_scm', 'py', 'pytest', 'pytest-runner', 'irc'), ('py', 'hgtools', 'setuptools_scm', 'pytest', 'pytest-runner', 'irc'), ('hgtools', 'setuptools_scm', 'py', 'pytest-runner', 'pytest', 'irc'), ('py', 'hgtools', 'setuptools_scm', 'pytest-runner', 'pytest', 'irc'), ('py', 'setuptools_scm', 'hgtools', 'pytest', 'pytest-runner', 'irc'), ('pytest', 'setuptools_scm', 'hgtools', 'pytest-runner', 'irc'), ('hgtools', 'setuptools_scm', 'pytest', 'pytest-runner', 'irc'), ('py', 'setuptools_scm', 'hgtools', 'pytest-runner', 'pytest', 'irc'), ('py', 'setuptools_scm', 'pytest', 'pytest-runner', 'hgtools', 'irc'), ('py', 'setuptools_scm', 'pytest-runner', 'pytest', 'hgtools', 'irc'), ('py', 'setuptools_scm', 'pytest', 'hgtools', 'pytest-runner', 'irc'), ('setuptools_scm', 'py', 'pytest', 'hgtools', 'pytest-runner', 'irc'), ('setuptools_scm', 'py', 'pytest-runner', 'hgtools', 'pytest', 'irc'), ('py', 'setuptools_scm', 'pytest-runner', 'hgtools', 'pytest', 'irc'), ('setuptools_scm', 'py', 'pytest', 'pytest-runner', 'hgtools', 'irc'), ]) self.assertIn(tuple(names), expected) # Test with extras dists, problems = finder.find('Jinja2 (== 2.6)') self.assertFalse(problems) actual = sorted([d.name_and_version for d in dists]) self.assertEqual(actual, ['Jinja2 (2.6)']) dists, problems = finder.find('Jinja2 [i18n] (== 2.6)') self.assertFalse(problems) actual = sorted([d.name_and_version for d in dists]) self.assertEqual(actual[-2], 'Jinja2 (2.6)') self.assertTrue(actual[-1].startswith('pytz (')) self.assertTrue(actual[0].startswith('Babel (')) actual = [d.build_time_dependency for d in dists] self.assertEqual(actual, [False, False, False]) # Now test with extra in dependency locator.clear_cache() dummy = make_dist('dummy', '0.1') dummy.metadata.run_requires = [{'requires': ['Jinja2 [i18n]']}] dists, problems = finder.find(dummy) self.assertFalse(problems) actual = sorted([d.name_and_version for d in dists]) self.assertTrue(actual[0].startswith('Babel (')) locator.clear_cache() dummy.metadata.run_requires = [{'requires': ['Jinja2']}] dists, problems = finder.find(dummy) self.assertFalse(problems) actual = sorted([d.name_and_version for d in dists]) self.assertTrue(actual[0].startswith('Jinja2 ('))