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 = [] for name in self.DISTROS_DIST + self.DISTROS_EGG + self.BAD_EGGS: dist = get_distribution(name, use_egg_info=True) self.assertNotEqual(dist, None) dists.append(dist) graph = depgraph.generate_graph(dists) buf = StringIO() depgraph.graph_to_dot(graph, 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_dependent_dists_egg(self): dists = [] for name in self.DISTROS_DIST + self.DISTROS_EGG: dist = get_distribution(name, use_egg_info=True) self.assertNotEqual(dist, None) dists.append(dist) choxie, grammar, towel, bacon, banana, strawberry, cheese = dists deps = [d.name for d in depgraph.dependent_dists(dists, choxie)] self.checkLists([], deps) deps = [d.name for d in depgraph.dependent_dists(dists, grammar)] self.checkLists([], deps) deps = [d.name for d in depgraph.dependent_dists(dists, towel)] self.checkLists(['choxie'], deps) deps = [d.name for d in depgraph.dependent_dists(dists, bacon)] self.checkLists(['choxie', 'towel-stuff', 'grammar'], deps) deps = [d.name for d in depgraph.dependent_dists(dists, strawberry)] self.checkLists(['banana'], deps) deps = [d.name for d in depgraph.dependent_dists(dists, cheese)] self.checkLists([], deps)
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 = [] for name in self.DISTROS_DIST + self.DISTROS_EGG: dist = get_distribution(name, use_egg_info=True) self.assertNotEqual(dist, None) dists.append(dist) graph = depgraph.generate_graph(dists) buf = StringIO() depgraph.graph_to_dot(graph, 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 _metadata(dispatcher, args, **kw): opts = _parse_args(args[1:], 'f:', []) if opts['args']: name = opts['args'][0] dist = get_distribution(name, use_egg_info=True) if dist is None: logger.warning('%r not installed', name) return 1 elif os.path.isfile('setup.cfg'): logger.info('searching local dir for metadata') dist = Distribution() # XXX use config module dist.parse_config_files() else: logger.warning('no argument given and no local setup.cfg found') return 1 metadata = dist.metadata if 'f' in opts: keys = (k for k in opts['f'] if k in metadata) else: keys = metadata.keys() for key in keys: if key in metadata: print(metadata._convert_name(key) + ':') value = metadata[key] if isinstance(value, list): for v in value: print(' ', v) else: print(' ', value.replace('\n', '\n '))
def test_repr(self): dists = [] for name in self.DISTROS_DIST + self.DISTROS_EGG + self.BAD_EGGS: dist = get_distribution(name, use_egg_info=True) self.assertNotEqual(dist, None) dists.append(dist) graph = depgraph.generate_graph(dists) self.assertTrue(repr(graph))
def _run_packaging_install(path): # XXX check for a valid setup.cfg? dist = Distribution() dist.parse_config_files() try: dist.run_command('install_dist') name = dist.metadata['Name'] return database.get_distribution(name) is not None except (IOError, os.error, PackagingError, CCompilerError) as msg: raise ValueError("Failed to install, " + str(msg))
def _graph(dispatcher, args, **kw): name = args[1] dist = get_distribution(name, use_egg_info=True) if dist is None: logger.warning('Distribution not found.') return 1 else: dists = get_distributions(use_egg_info=True) graph = generate_graph(dists) print(graph.repr_node(dist))
def finalize_options(self): self.build_lib = self.get_finalized_command("build").build_lib for requirement in self.tests_require: if get_distribution(requirement) is None: logger.warning("test dependency %s is not installed, " "tests may fail", requirement) if (not self.suite and not self.runner and self.get_ut_with_discovery() is None): raise PackagingOptionError( "no test discovery available, please give a 'suite' or " "'runner' option or install unittest2")
def test_dependent_dists(self): dists = [] for name in self.DISTROS_DIST: dist = get_distribution(name) self.assertNotEqual(dist, None) dists.append(dist) choxie, grammar, towel = dists deps = [d.name for d in depgraph.dependent_dists(dists, choxie)] self.checkLists([], deps) deps = [d.name for d in depgraph.dependent_dists(dists, grammar)] self.checkLists([], deps) deps = [d.name for d in depgraph.dependent_dists(dists, towel)] self.checkLists(['choxie'], deps)
def test_generate_graph_egg(self): dists = [] for name in self.DISTROS_DIST + self.DISTROS_EGG: dist = get_distribution(name, use_egg_info=True) self.assertNotEqual(dist, None) dists.append(dist) choxie, grammar, towel, bacon, banana, strawberry, cheese = dists graph = depgraph.generate_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[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[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[bacon], []) deps = [(x.name, y) for x, y in graph.adjacency_list[banana]] self.checkLists([('strawberry', 'strawberry (>=0.5)')], deps) self.checkLists(graph.missing[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[strawberry], []) deps = [(x.name, y) for x, y in graph.adjacency_list[cheese]] self.checkLists([], deps) self.checkLists(graph.missing[cheese], [])
def test_generate_graph(self): dists = [] for name in self.DISTROS_DIST: dist = get_distribution(name) self.assertNotEqual(dist, None) dists.append(dist) choxie, grammar, towel = dists graph = depgraph.generate_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 remove(project_name, paths=None, auto_confirm=True): """Removes a single project from the installation. Returns True on success """ dist = get_distribution(project_name, use_egg_info=True, paths=paths) if dist is None: raise PackagingError('Distribution %r not found' % project_name) files = dist.list_installed_files(local=True) rmdirs = [] rmfiles = [] tmp = tempfile.mkdtemp(prefix=project_name + '-uninstall') def _move_file(source, target): try: os.rename(source, target) except OSError as err: return err return None success = True error = None try: for file_, md5, size in files: if os.path.isfile(file_): dirname, filename = os.path.split(file_) tmpfile = os.path.join(tmp, filename) try: error = _move_file(file_, tmpfile) if error is not None: success = False break finally: if not os.path.isfile(file_): os.rename(tmpfile, file_) if file_ not in rmfiles: rmfiles.append(file_) if dirname not in rmdirs: rmdirs.append(dirname) finally: shutil.rmtree(tmp) if not success: logger.info('%r cannot be removed.', project_name) logger.info('Error: %s', error) return False logger.info('Removing %r: ', project_name) for file_ in rmfiles: logger.info(' %s', file_) # Taken from the pip project if auto_confirm: response = 'y' else: response = ask('Proceed (y/n)? ', ('y', 'n')) if response == 'y': file_count = 0 for file_ in rmfiles: os.remove(file_) file_count += 1 dir_count = 0 for dirname in rmdirs: if not os.path.exists(dirname): # could continue files_count = 0 for root, dir, files in os.walk(dirname): files_count += len(files) if files_count > 0: # XXX Warning continue # empty dirs with only empty dirs if os.stat(dirname).st_mode & stat.S_IWUSR: # XXX Add a callable in shutil.rmtree to count # the number of deleted elements shutil.rmtree(dirname) dir_count += 1 # removing the top path # XXX count it ? if os.path.exists(dist.path): shutil.rmtree(dist.path) logger.info('Success: removed %d files and %d dirs', file_count, dir_count) return True
def test_get_distribution(self): # Test for looking up a distribution by name. # Test the lookup of the towel-stuff distribution name = 'towel-stuff' # Note: This is different from the directory name # Lookup the distribution dist = get_distribution(name) self.assertIsInstance(dist, Distribution) self.assertEqual(dist.name, name) # Verify that an unknown distribution returns None self.assertIsNone(get_distribution('bogus')) # Verify partial name matching doesn't work self.assertIsNone(get_distribution('towel')) # Verify that it does not find egg-info distributions, when not # instructed to self.assertIsNone(get_distribution('bacon')) self.assertIsNone(get_distribution('cheese')) self.assertIsNone(get_distribution('strawberry')) self.assertIsNone(get_distribution('banana')) # Now check that it works well in both situations, when egg-info # is a file and directory respectively. dist = get_distribution('cheese', use_egg_info=True) self.assertIsInstance(dist, EggInfoDistribution) self.assertEqual(dist.name, 'cheese') dist = get_distribution('bacon', use_egg_info=True) self.assertIsInstance(dist, EggInfoDistribution) self.assertEqual(dist.name, 'bacon') dist = get_distribution('banana', use_egg_info=True) self.assertIsInstance(dist, EggInfoDistribution) self.assertEqual(dist.name, 'banana') dist = get_distribution('strawberry', use_egg_info=True) self.assertIsInstance(dist, EggInfoDistribution) self.assertEqual(dist.name, 'strawberry')