pidgin/purple-plugin-pack

Parents 92cddca235cf
Children 2e59c360d490
Make the plugin_pack.py script compatible with both python 2.6+ and python 3.
Fixes #3.
  • +446 -461
    plugin_pack.py
  • --- a/plugin_pack.py Fri Jan 17 23:14:33 2014 +0530
    +++ b/plugin_pack.py Sat Feb 01 20:48:53 2014 -0500
    @@ -32,582 +32,567 @@
    Commands:
    """
    -import ConfigParser
    +from __future__ import print_function
    import getopt
    import glob
    import os.path
    import string
    import sys
    -webpage = 'http://plugins.guifications.org/'
    +try:
    + import configparser
    +except ImportError:
    + import ConfigParser as configparser
    -def printerr(msg):
    - print >> sys.stderr, msg
    +WEBPAGE = 'https://bitbucket.org/rekkanoryo/purple-plugin-pack'
    +
    +def printerr(*msg):
    + print(msg, file=sys.stderr)
    + #print(msg)
    class Plugin:
    - name = ''
    - directory = ''
    - type = ''
    - depends = []
    - provides = ''
    - summary = ''
    - description = ''
    - authors = []
    - introduced = ''
    - notes = ''
    + name = ''
    + directory = ''
    + type = ''
    + depends = []
    + provides = ''
    + summary = ''
    + description = ''
    + authors = []
    + introduced = ''
    + notes = ''
    - def __init__(self, directory, name, parser):
    - self.name = name
    + def __init__(self, directory, name, parser):
    + self.name = name
    - self.directory = directory
    + self.directory = directory
    - self.type = parser.get(name, 'type')
    - self.depends = parser.get(name, 'depends').split()
    - self.provides = parser.get(name, 'provides')
    - self.summary = parser.get(name, 'summary')
    - self.description = parser.get(name, 'description')
    - self.authors = parser.get(name, 'authors').split(',')
    - self.introduced = parser.get(name, 'introduced')
    + self.type = parser.get(name, 'type')
    + self.depends = parser.get(name, 'depends').split()
    + self.provides = parser.get(name, 'provides')
    + self.summary = parser.get(name, 'summary')
    + self.description = parser.get(name, 'description')
    + self.authors = parser.get(name, 'authors').split(',')
    + self.introduced = parser.get(name, 'introduced')
    - if parser.has_option(name, 'notes'):
    - self.notes = parser.get(name, 'notes')
    + if parser.has_option(name, 'notes'):
    + self.notes = parser.get(name, 'notes')
    - if self.type != 'default' and self.type != 'incomplete' and self.type != 'abusive':
    - printerr('\'%s\' has an unknown type of \'%s\'!' % (self.name, self.type))
    + if self.type != 'default' and self.type != 'incomplete' and self.type != 'abusive':
    + printerr('\'%s\' has an unknown type of \'%s\'!' % (self.name, self.type))
    - def __str__(self):
    - output = 'name: %s\n' % self.name
    - output += 'authors: %s\n' % string.join(self.authors, ', ')
    - output += 'type: %s\n' % self.type
    - output += 'depends: %s\n' % string.join(self.depends, ' ')
    - output += 'provides: %s\n' % self.provides
    - output += 'directory: %s\n' % self.directory
    - output += 'summary: %s\n' % self.summary
    - output += 'description: %s\n' % self.description
    + def __str__(self):
    + output = 'name: {}\n'.format(self.name)
    + output += 'authors: {}\n'.format(string.join(self.authors, ', '))
    + output += 'type: {}\n'.format(self.type)
    + output += 'depends: {}\n'.format(string.join(self.depends, ' '))
    + output += 'provides: {}\n'.format(self.provides)
    + output += 'directory: {}\n'.format(self.directory)
    + output += 'summary: {}\n'.format(self.summary)
    + output += 'description: {}\n'.format(self.description)
    - if self.notes:
    - output += 'notes: %s\n' % self.notes
    + if self.notes:
    + output += 'notes: {}\n'.format(self.notes)
    - return output
    + return output
    class PluginPack:
    - commands = {}
    - plugins = {}
    + commands = {}
    + plugins = {}
    - def load_plugins(self, types, depends):
    - if len(types) == 0:
    - types = None
    + def load_plugins(self, types, depends):
    + if len(types) == 0:
    + types = None
    - if len(depends) == 0:
    - depends = None
    + if len(depends) == 0:
    + depends = None
    - for file in glob.glob('*/plugins.cfg'):
    - parser = ConfigParser.ConfigParser()
    + for file in glob.glob('*/plugins.cfg'):
    + parser = configparser.ConfigParser()
    - try:
    - parser.read(file)
    - except ConfigParser.ParsingError, msg:
    - printerr('Failed to parse \'%s\':\n%s' % (file, msg))
    - continue
    + try:
    + parser.read(file)
    + except configparser.ParsingError as msg:
    + printerr('Failed to parse \'%s\':\n%s' % (file, msg))
    + continue
    - for plugin in parser.sections():
    - p = Plugin(os.path.dirname(file), plugin, parser)
    + for plugin in parser.sections():
    + p = Plugin(os.path.dirname(file), plugin, parser)
    - # this is kind of hacky, but if we have types, we check to see
    - # if the type is in list of types to load.
    - if types and not p.type in types:
    - continue
    -
    - # now we check if the give plugins depends match the search
    - # depends
    - if depends:
    - if len(set(depends).intersection(set(p.depends))) == 0:
    - continue
    -
    - self.plugins[p.provides] = p
    + # this is kind of hacky, but if we have types, we check to see
    + # if the type is in list of types to load.
    + if types and not p.type in types:
    + continue
    +
    + # now we check if the give plugins depends match the search
    + # depends
    + if depends:
    + if len(set(depends).intersection(set(p.depends))) == 0:
    + continue
    - def list_type(self, type):
    - list = []
    + self.plugins[p.provides] = p
    - for name in self.plugins.keys():
    - plugin = self.plugins[name]
    - if plugin.type == type:
    - list.append(plugin)
    + def list_type(self, type):
    + list = []
    - list.sort()
    -
    - return list
    + for name in self.plugins.keys():
    + plugin = self.plugins[name]
    + if plugin.type == type:
    + list.append(plugin)
    - def list_dep(self, dep):
    - list = []
    + list.sort()
    - for name in self.plugins.keys():
    - plugin = self.plugins[name]
    + return list
    - if dep in plugin.depends:
    - list.append(plugin)
    -
    - list.sort()
    + def list_dep(self, dep):
    + list = []
    - return list
    + for name in self.plugins.keys():
    + plugin = self.plugins[name]
    - def print_names(self, list):
    - names = []
    + if dep in plugin.depends:
    + list.append(plugin)
    - for plugin in list:
    - names.append(plugin.name)
    + list.sort()
    - print string.join(names, ',')
    + return list
    - def default_plugins(self):
    - return self.list_type('default')
    + def print_names(self, list):
    + names = []
    - def abusive_plugins(self):
    - return self.list_type('abusive')
    + for plugin in list:
    + names.append(plugin.name)
    - def incomplete_plugins(self):
    - return self.list_type('incomplete')
    + print(string.join(names, ','))
    - def purple_plugins(self):
    - return self.list_dep('purple')
    + def default_plugins(self):
    + return self.list_type('default')
    - def finch_plugins(self):
    - return self.list_dep('finch')
    + def abusive_plugins(self):
    + return self.list_type('abusive')
    - def pidgin_plugins(self):
    - return self.list_dep('pidgin')
    + def incomplete_plugins(self):
    + return self.list_type('incomplete')
    - def unique_dirs(self):
    - dirs = {}
    - for name in self.plugins.keys():
    - dirs[self.plugins[name].directory] = 1
    + def purple_plugins(self):
    + return self.list_dep('purple')
    - dirs = dirs.keys()
    - dirs.sort()
    + def finch_plugins(self):
    + return self.list_dep('finch')
    - return dirs
    + def pidgin_plugins(self):
    + return self.list_dep('pidgin')
    - def help(self, args):
    - """Displays information about other commands"""
    - try:
    - cmd = self.commands[args[0]]
    - print cmd.__doc__
    - except KeyError:
    - print 'command \'%s\' was not found' % args[0]
    - except IndexError:
    - print '%s' % (self.help.__doc__)
    - print
    - print 'help usage:'
    - print ' help <command>'
    - print
    - print 'Available commands:'
    + def unique_dirs(self):
    + dirs = {}
    + for name in self.plugins.keys():
    + dirs[self.plugins[name].directory] = 1
    +
    + dirs = sorted(dirs.keys())
    +
    + return dirs
    - cmds = self.commands.keys()
    - cmds.remove('help')
    - cmds.sort()
    - print ' %s' % (string.join(cmds, ' '))
    - commands['help'] = help
    -
    - def dist_dirs(self, args):
    - """Displays a list of all plugin directories to included in the distribution"""
    - print string.join(self.unique_dirs(), ' ')
    - commands['dist_dirs'] = dist_dirs
    + def help(self, args):
    + """Displays information about other commands"""
    + try:
    + cmd = self.commands[args[0]]
    + print(cmd.__doc__)
    + except KeyError:
    + print('command \'{}\' was not found'.format(args[0]))
    + except IndexError:
    + print('{}'.format(self.help.__doc__))
    + print('\nhelp usage:\n help <command>\n\nAvailable commands:')
    - def build_dirs(self, args):
    - """Displays a list of the plugins that can be built"""
    - if len(args) != 2:
    - printerr('build_dirs expects 2 arguments:')
    - printerr('\ta comma separated list of dependencies')
    - printerr('\ta comma separated list of plugins to build')
    - sys.exit(1)
    + cmds = self.commands.keys()
    + cmds.remove('help')
    + cmds.sort()
    + print(' {}'.format(string.join(cmds, ' ')))
    + commands['help'] = help
    - # store the external depedencies
    - externals = args[0].split(',')
    -
    - deps = {}
    + def dist_dirs(self, args):
    + """Displays a list of all plugin directories to included in the distribution"""
    + print(string.join(self.unique_dirs(), ' '))
    + commands['dist_dirs'] = dist_dirs
    - # run through the provided dependencies, setting their dependencies to
    - # nothing since we know we already have them
    - for d in externals:
    - deps[d] = []
    + def build_dirs(self, args):
    + """Displays a list of the plugins that can be built"""
    + if len(args) != 2:
    + printerr('build_dirs expects 2 arguments:')
    + printerr('\ta comma separated list of dependencies')
    + printerr('\ta comma separated list of plugins to build')
    + sys.exit(1)
    - # now run through the plugins adding their deps to the dictionary
    - for name in self.plugins.keys():
    - plugin = self.plugins[name]
    + # store the external depedencies
    + externals = args[0].split(',')
    - deps[plugin.provides] = plugin.depends
    + deps = {}
    - # run through the requested plugins and store their plugin instance in check
    - check = []
    - for provides in args[1].split(','):
    - try:
    - if provides == 'all':
    - defaults = []
    - for p in self.default_plugins():
    - defaults.append(p.provides)
    + # run through the provided dependencies, setting their dependencies to
    + # nothing since we know we already have them
    + for d in externals:
    + deps[d] = []
    +
    + # now run through the plugins adding their deps to the dictionary
    + for name in self.plugins.keys():
    + plugin = self.plugins[name]
    +
    + deps[plugin.provides] = plugin.depends
    - check += defaults
    -
    - continue
    + # run through the requested plugins and store their plugin instance in check
    + check = []
    + for provides in args[1].split(','):
    + try:
    + if provides == 'all':
    + defaults = []
    + for p in self.default_plugins():
    + defaults.append(p.provides)
    - plugin = self.plugins[provides]
    - check.append(plugin.provides)
    - except KeyError:
    - continue
    -
    - # convert our list of plugins to check into a set to remove dupes
    - #check = set(check)
    + check += defaults
    - # create our list of plugins to build
    - build = []
    + continue
    - # now define a function to check our deps
    - def has_deps(provides):
    - # don't add anything to build more than once
    - if provides in build:
    - return True
    + plugin = self.plugins[provides]
    + check.append(plugin.provides)
    + except KeyError:
    + continue
    - try:
    - dep_list = deps[provides]
    - except KeyError:
    - return False
    + # convert our list of plugins to check into a set to remove dupes
    + #check = set(check)
    - # now check the dependencies
    - for dep in dep_list:
    - if '|' in dep:
    - count = 0
    - for d in dep.split('|'):
    - if has_deps(d):
    - count += 1
    + # create our list of plugins to build
    + build = []
    - if count == 0:
    - return False
    - else:
    - if not has_deps(dep):
    - return False
    + # now define a function to check our deps
    + def has_deps(provides):
    + # don't add anything to build more than once
    + if provides in build:
    + return True
    +
    + try:
    + dep_list = deps[provides]
    + except KeyError:
    + return False
    - # make sure the provides isn't an external
    - if not provides in externals:
    - build.append(provides)
    -
    - # everything checks out!
    - return True
    + # now check the dependencies
    + for dep in dep_list:
    + if '|' in dep:
    + count = 0
    + for d in dep.split('|'):
    + if has_deps(d):
    + count += 1
    - # check all the plugins we were told to for their dependencies
    - for c in check:
    - has_deps(c)
    -
    - # now create a list of all directories to build
    - output = []
    + if count == 0:
    + return False
    + else:
    + if not has_deps(dep):
    + return False
    - for provides in build:
    - plugin = self.plugins[provides]
    + # make sure the provides isn't an external
    + if not provides in externals:
    + build.append(provides)
    - output.append(plugin.directory)
    -
    - output.sort()
    + # everything checks out!
    + return True
    - print "%s" % (string.join(output, ','))
    - commands['build_dirs'] = build_dirs
    -
    - def list_plugins(self, args):
    - """Displays a list similiar to 'dpkg -l' about the plugin pack"""
    + # check all the plugins we were told to for their dependencies
    + for c in check:
    + has_deps(c)
    +
    + # now create a list of all directories to build
    + output = []
    - data = {}
    + for provides in build:
    + plugin = self.plugins[provides]
    +
    + output.append(plugin.directory)
    +
    + output.sort()
    - # create an array for the widths, we initialize it to the lengths of
    - # the title strings. We ignore summary, since that one shouldn't
    - # matter.
    - widths = [4, 8, 0]
    + print("{}".format(string.join(output, ',')))
    + commands['build_dirs'] = build_dirs
    +
    + def list_plugins(self, args):
    + """Displays a list similiar to 'dpkg -l' about the plugin pack"""
    - for p in self.plugins.keys():
    - plugin = self.plugins[p]
    + data = {}
    - if plugin.type == 'abusive':
    - type = 'a'
    - elif plugin.type == 'incomplete':
    - type = 'i'
    - else:
    - type = 'd'
    + # create an array for the widths, we initialize it to the lengths of
    + # the title strings. We ignore summary, since that one shouldn't
    + # matter.
    + widths = [4, 8, 0]
    - if 'finch' in plugin.depends:
    - ui = 'f'
    - elif 'pidgin' in plugin.depends:
    - ui = 'p'
    - elif 'purple' in plugin.depends:
    - ui = 'r'
    - else:
    - ui = 'u'
    + for p in self.plugins.keys():
    + plugin = self.plugins[p]
    +
    + if plugin.type == 'abusive':
    + type = 'a'
    + elif plugin.type == 'incomplete':
    + type = 'i'
    + else:
    + type = 'd'
    - widths[0] = max(widths[0], len(plugin.name))
    - widths[1] = max(widths[1], len(plugin.provides))
    - widths[2] = max(widths[2], len(plugin.summary))
    + if 'finch' in plugin.depends:
    + ui = 'f'
    + elif 'pidgin' in plugin.depends:
    + ui = 'p'
    + elif 'purple' in plugin.depends:
    + ui = 'r'
    + else:
    + ui = 'u'
    - data[plugin.provides] = [type, ui, plugin.name, plugin.provides, plugin.summary]
    -
    - print 'Type=Default/Incomplete/Abusive'
    - print '| UI=Finch/Pidgin/puRple/Unknown'
    - print '|/ Name%s Provides%s Summary' % (' ' * (widths[0] - 4), ' ' * (widths[1] - 8))
    - print '++-%s-%s-%s' % ('=' * (widths[0]), '=' * (widths[1]), '=' * (widths[2]))
    + widths[0] = max(widths[0], len(plugin.name))
    + widths[1] = max(widths[1], len(plugin.provides))
    + widths[2] = max(widths[2], len(plugin.summary))
    - # create the format var
    - fmt = '%%s%%s %%-%ds %%-%ds %%s' % (widths[0], widths[1]) #, widths[2])
    + data[plugin.provides] = [type, ui, plugin.name, plugin.provides, plugin.summary]
    - # now loop through the list again, with everything formatted
    - list = data.keys()
    - list.sort()
    + print('Type=Default/Incomplete/Abusive')
    + print('| UI=Finch/Pidgin/puRple/Unknown')
    + print('|/ Name{} Provides{} Summary'.format(' ' * (widths[0] - 4), ' ' * (widths[1] - 8)))
    + print('++-{}-{}-{}'.format('=' * (widths[0]), '=' * (widths[1]), '=' * (widths[2])))
    - for p in list:
    - d = data[p]
    - print fmt % (d[0], d[1], d[2], d[3], d[4])
    - commands['list'] = list_plugins
    + # create the format var
    + fmt = '{}{} {:<' + widths[0] + '} {:<' + widths[1] + '} {}'
    - def config_file(self, args):
    - """Outputs the contents for the file to be m4_include()'d from configure"""
    - uniqdirs = self.unique_dirs()
    + # now loop through the list again, with everything formatted
    + list = data.keys()
    + list.sort()
    - # add our --with-plugins option
    - print 'AC_ARG_WITH(plugins,'
    - print ' AC_HELP_STRING([--with-plugins], [what plugins to build]),'
    - print ' ,with_plugins=all)'
    - print 'if test -z $with_plugins ; then'
    - print '\twith_plugins=all'
    - print 'fi'
    + for p in list:
    + d = data[p]
    + print(fmt.format(d[0], d[1], d[2], d[3], d[4]))
    + commands['list'] = list_plugins
    +
    + def config_file(self, args):
    + """Outputs the contents for the file to be m4_include()'d from configure"""
    + uniqdirs = self.unique_dirs()
    + dirs = ''
    +
    + for d in uniqdirs:
    + dirs = dirs + ' ' + d
    - # determine and add our output files
    - print 'PP_DIST_DIRS="%s"' % (string.join(uniqdirs, ' '))
    - print 'AC_SUBST(PP_DIST_DIRS)'
    - print
    - print 'AC_CONFIG_FILES(['
    - for dir in uniqdirs:
    - print '\t%s/Makefile' % (dir)
    - print '])'
    - print
    + # add our --with-plugins option
    + print('{}\n{}\n{}\n{}\n{}\n{}'.format('AC_ARG_WITH(plugins,',
    + ' AC_HELP_STRING([--with-plugins], [what plugins to build]),',
    + ' ,with_plugins=all)', 'if test -z $with_plugins ; then',
    + '\twith_plugins=all', 'fi'))
    - # setup a second call to determine the plugins to be built
    - print 'PP_BUILD=`$PYTHON $srcdir/plugin_pack.py build_dirs $DEPENDENCIES $with_plugins`'
    - print
    - print 'PP_BUILD_DIRS=`echo $PP_BUILD | sed \'s/,/\ /g\'`'
    - print 'AC_SUBST(PP_BUILD_DIRS)'
    - print
    - print 'PP_PURPLE_BUILD="$PYTHON $srcdir/plugin_pack.py -p show_names $PP_BUILD"'
    - print 'PP_PIDGIN_BUILD="$PYTHON $srcdir/plugin_pack.py -P show_names $PP_BUILD"'
    - print 'PP_FINCH_BUILD="$PYTHON $srcdir/plugin_pack.py -f show_names $PP_BUILD"'
    - commands['config_file'] = config_file
    + # determine and add our output files
    + print('{}\n{}\n\n{}'.format(
    + 'PP_DIST_DIRS="{}"'.format(dirs),
    + 'AC_SUBST(PP_DIST_DIRS)', 'AC_CONFIG_FILES(['))
    + for dir in uniqdirs:
    + print('\t{}/Makefile'.format(dir))
    + print('])\n')
    - def dependency_graph(self, args):
    - """Outputs a graphviz script showing plugin dependencies"""
    - def node_label(plugin):
    - node = plugin.provides.replace('-', '_')
    - label = plugin.name
    -
    - return node, label
    -
    - def print_plugins(list):
    - for plugin in list:
    - node, label = node_label(plugin)
    -
    - print '\t%s[label="%s"];' % (node, label)
    + # setup a second call to determine the plugins to be built
    + print('{}\n\n{}\n{}\n\n{}\n{}\n{}'.format(
    + 'PP_BUILD=`$PYTHON $srcdir/plugin_pack.py build_dirs $DEPENDENCIES $with_plugins`',
    + 'PP_BUILD_DIRS=`echo $PP_BUILD | sed \'s/,/\ /g\'`',
    + 'AC_SUBST(PP_BUILD_DIRS)',
    + 'PP_PURPLE_BUILD="$PYTHON $srcdir/plugin_pack.py -p show_names $PP_BUILD"',
    + 'PP_PIDGIN_BUILD="$PYTHON $srcdir/plugin_pack.py -P show_names $PP_BUILD"',
    + 'PP_FINCH_BUILD="$PYTHON $srcdir/plugin_pack.py -f show_names $PP_BUILD"'))
    + commands['config_file'] = config_file
    - print 'digraph {'
    - print '\tlabel="Dependency Graph";'
    - print '\tlabelloc="t";'
    - print '\tsplines=TRUE;'
    - print '\toverlap=FALSE;'
    - print
    - print '\tnode[fontname="sans", fontsize="8", style="filled"];'
    - print
    + def dependency_graph(self, args):
    + """Outputs a graphviz script showing plugin dependencies"""
    + def node_label(plugin):
    + node = plugin.provides.replace('-', '_')
    + label = plugin.name
    +
    + return node, label
    - # run through the default plugins
    - print '\t/* default plugins */'
    - print '\tnode[fillcolor="palegreen",shape="tab"];'
    - print_plugins(self.default_plugins())
    - print
    + def print_plugins(list):
    + for plugin in list:
    + node, label = node_label(plugin)
    - # run through the incomplete plugins
    - print '\t/* incomplete plugins */'
    - print '\tnode[fillcolor="lightyellow1",shape="note"];'
    - print_plugins(self.incomplete_plugins())
    - print
    + print('\t{}[label="{}"];'.format(node, label))
    +
    + print('{}\n{}\n{}\n{}\n{}\n\n{}\n'.format('digraph {',
    + '\tlabel="Dependency Graph";', '\tlabelloc="t";', '\tsplines=TRUE;',
    + '\toverlap=FALSE;',
    + '\tnode[fontname="sans", fontsize="8", style="filled"];'))
    - # run through the abusive plugins
    - print '\t/* abusive plugins */'
    - print '\tnode[fillcolor="lightpink",shape="octagon"];'
    - print_plugins(self.abusive_plugins())
    - print
    + # run through the default plugins
    + print('{}\n{}'.format('\t/* default plugins */',
    + '\tnode[fillcolor="palegreen",shape="tab"];'))
    + print_plugins(self.default_plugins())
    + print('')
    - # run through again, this time showing the relations
    - print '\t/* dependencies'
    - print '\t * exteranl ones that don\'t have nodes get colored to the following'
    - print '\t */'
    - print '\tnode[fillcolor="powderblue", shape="egg"];'
    + # run through the incomplete plugins
    + print('{}\n{}'.format('\t/* incomplete plugins */',
    + '\tnode[fillcolor="lightyellow1",shape="note"];'))
    + print_plugins(self.incomplete_plugins())
    + print('')
    - for name in self.plugins.keys():
    - plugin = self.plugins[name]
    -
    - node, label = node_label(plugin)
    + # run through the abusive plugins
    + print('{}\n{}'.format('\t/* abusive plugins */',
    + '\tnode[fillcolor="lightpink",shape="octagon"];'))
    + print_plugins(self.abusive_plugins())
    + print('')
    - for dep in plugin.depends:
    - dep = dep.replace('-', '_')
    - print '\t%s -> %s;' % (node, dep)
    + # run through again, this time showing the relations
    + print('{}\n{}\n{}\n{}'.format('\t/* dependencies',
    + '\t * external ones that don\'t have nodes get colored to the following',
    + '\t */', '\tnode[fillcolor="powderblue", shape="egg"];'))
    - print '}'
    - commands['dependency_graph'] = dependency_graph
    + for name in self.plugins.keys():
    + plugin = self.plugins[name]
    +
    + node, label = node_label(plugin)
    - def debian_description(self, args):
    - """Outputs the description for the Debian packages"""
    - print 'Description: %d useful plugins for Pidgin, Finch, and Purple' % len(self.plugins)
    - print ' The Plugin Pack is a collection of many simple-yet-useful plugins for Pidgin,'
    - print ' Finch, and Purple. You will find a summary of each plugin below. For more'
    - print ' about an individual plugin, please see %s' % webpage
    - print ' .'
    - print ' Note: not all %d of these plugins are currently usable' % len(self.plugins)
    -
    - list = self.plugins.keys()
    - list.sort()
    - for key in list:
    - plugin = self.plugins[key]
    - print ' .'
    - print ' %s: %s' % (plugin.name, plugin.summary)
    + for dep in plugin.depends:
    + dep = dep.replace('-', '_')
    + print('\t() -> {};'.format(node, dep))
    +
    + print('}')
    + commands['dependency_graph'] = dependency_graph
    - print ' .'
    - print ' .'
    - print ' Homepage: %s' % webpage
    - commands['debian_description'] = debian_description
    -
    - def show_names(self, args):
    - """Displays the names of the given comma separated list of provides"""
    + def debian_description(self, args):
    + """Outputs the description for the Debian packages"""
    + print('Description: %d useful plugins for Pidgin, Finch, and Purple'.format(len(self.plugins)))
    + print(' The Plugin Pack is a collection of many simple-yet-useful plugins for Pidgin,')
    + print(' Finch, and Purple. You will find a summary of each plugin below. For more')
    + print(' about an individual plugin, please see {}\n .'.format(WEBPAGE))
    + print(' Note: not all {} of these plugins are currently usable'.format(len(self.plugins)))
    +
    + list = self.plugins.keys()
    + list.sort()
    + for key in list:
    + plugin = self.plugins[key]
    + print(' .')
    + print(' {}: {}'.format(plugin.name, plugin.summary))
    - if len(args) == 0 or len(args[0]) == 0:
    - printerr('show_names expects a comma separated list of provides')
    - sys.exit(1)
    + print(' .\n .\n Homepage: {}'.format(WEBPAGE))
    + commands['debian_description'] = debian_description
    - provides = args[0].split(',')
    - if len(provides) == 0:
    - print "none"
    + def show_names(self, args):
    + """Displays the names of the given comma separated list of provides"""
    - line = " "
    -
    - for provide in provides:
    - if not provide in self.plugins:
    - continue
    + if len(args) == 0 or len(args[0]) == 0:
    + printerr('show_names expects a comma separated list of provides')
    + sys.exit(1)
    - name = self.plugins[provide].name
    + provides = args[0].split(',')
    + if len(provides) == 0:
    + print("none")
    - if len(line) + len(name) + 2 > 75:
    - print line.rstrip(',')
    - line = ' '
    -
    - line += ' %s,' % name
    + line = " "
    - if len(line) > 1:
    - print line.rstrip(',')
    - commands['show_names'] = show_names
    + for provide in provides:
    + if not provide in self.plugins:
    + continue
    +
    + name = self.plugins[provide].name
    - def info(self, args):
    - """Displays all information about the given plugins"""
    - for p in args:
    - try:
    - print self.plugins[p].__str__().strip()
    - except KeyError:
    - print 'Failed to find a plugin that provides \'%s\'' % (p)
    + if len(line) + len(name) + 2 > 75:
    + print(line.rstrip(','))
    + line = ' '
    +
    + line += ' {},'.format(name)
    - print
    - commands['info'] = info
    + if len(line) > 1:
    + print(line.rstrip(','))
    + commands['show_names'] = show_names
    - def stats(self, args):
    - """Displays stats about the plugin pack"""
    - counts = {}
    -
    - counts['total'] = len(self.plugins)
    - counts['default'] = len(self.default_plugins())
    - counts['incomplete'] = len(self.incomplete_plugins())
    - counts['abusive'] = len(self.abusive_plugins())
    - counts['purple'] = len(self.purple_plugins())
    - counts['finch'] = len(self.finch_plugins())
    - counts['pidgin'] = len(self.pidgin_plugins())
    -
    - def value(val):
    - return "%3d (%6.2f%%)" % (val, (float(val) / float(counts['total'])) * 100.0)
    + def info(self, args):
    + """Displays all information about the given plugins"""
    + for p in args:
    + try:
    + print(self.plugins[p].__str__().strip() + '\n')
    + except KeyError:
    + print('Failed to find a plugin that provides \'{}\'\n'.format(p))
    + commands['info'] = info
    - print "Purple Plugin Pack Stats"
    - print ""
    - print "%d plugins in total" % (counts['total'])
    - print
    - print "Status:"
    - print " complete: %s" % (value(counts['default']))
    - print " incomplete: %s" % (value(counts['incomplete']))
    - print " abusive: %s" % (value(counts['abusive']))
    - print ""
    - print "Type:"
    - print " purple: %s" % (value(counts['purple']))
    - print " finch: %s" % (value(counts['finch']))
    - print " pidgin: %s" % (value(counts['pidgin']))
    - commands['stats'] = stats
    + def stats(self, args):
    + """Displays stats about the plugin pack"""
    + counts = {}
    +
    + counts['total'] = len(self.plugins)
    + counts['default'] = len(self.default_plugins())
    + counts['incomplete'] = len(self.incomplete_plugins())
    + counts['abusive'] = len(self.abusive_plugins())
    + counts['purple'] = len(self.purple_plugins())
    + counts['finch'] = len(self.finch_plugins())
    + counts['pidgin'] = len(self.pidgin_plugins())
    +
    + def value(val):
    + return "%3d ({:6.2}%)".format(val, (float(val) / float(counts['total'])) * 100.0)
    +
    + print('{}\n\n{}\n\n{}\n{}\n{}\n{}\n\n{}\n{}\n{}\n{}'.format(
    + "Purple Plugin Pack Stats", "{} plugins in total".format(counts['total']),
    + "Status:", " complete: {}".format(value(counts['default'])),
    + " incomplete: {}".format(value(counts['incomplete'])),
    + " abusive: {}".format(value(counts['abusive'])), "Type:",
    + " purple: {}".format(value(counts['purple'])),
    + " finch: {}".format(value(counts['finch'])),
    + " pidgin: {}".format(value(counts['pidgin']))))
    + commands['stats'] = stats
    def show_usage(pp, exitcode):
    - print __doc__
    + print(__doc__)
    - cmds = pp.commands.keys()
    - cmds.sort()
    -
    - for cmd in cmds:
    - print " %-20s %s" % (cmd, pp.commands[cmd].__doc__)
    + cmds = pp.commands.keys()
    + cmds.sort()
    +
    + for cmd in cmds:
    + print(" {:<-20} {}".format(cmd, pp.commands[cmd].__doc__))
    - print ""
    + print("")
    - sys.exit(exitcode)
    + sys.exit(exitcode)
    def main():
    - # create our main instance
    - pp = PluginPack()
    + # create our main instance
    + pp = PluginPack()
    - types = []
    - depends = []
    + types = []
    + depends = []
    - try:
    - shortopts = 'adfiPp'
    + try:
    + shortopts = 'adfiPp'
    - opts, args = getopt.getopt(sys.argv[1:], shortopts)
    - except getopt.error, msg:
    - print msg
    - show_usage(pp, 1)
    + opts, args = getopt.getopt(sys.argv[1:], shortopts)
    + except getopt.error as msg:
    + print(msg)
    + show_usage(pp, 1)
    - for o, a in opts:
    - if o == '-a':
    - types.append('abusive')
    - elif o == '-d':
    - types.append('default')
    - elif o == '-i':
    - types.append('incomplete')
    - elif o == '-f':
    - depends.append('finch')
    - elif o == '-P':
    - depends.append('pidgin')
    - elif o == '-p':
    - depends.append('purple')
    + for o, a in opts:
    + if o == '-a':
    + types.append('abusive')
    + elif o == '-d':
    + types.append('default')
    + elif o == '-i':
    + types.append('incomplete')
    + elif o == '-f':
    + depends.append('finch')
    + elif o == '-P':
    + depends.append('pidgin')
    + elif o == '-p':
    + depends.append('purple')
    - # load the plugins that have been requested, if both lists are empty, all
    - # plugins are loaded
    - pp.load_plugins(types, depends)
    + # load the plugins that have been requested, if both lists are empty, all
    + # plugins are loaded
    + pp.load_plugins(types, depends)
    - if(len(args) == 0):
    - show_usage(pp, 1)
    + if(len(args) == 0):
    + show_usage(pp, 1)
    - cmd = args[0]
    - args = args[1:]
    + cmd = args[0]
    + args = args[1:]
    - try:
    - pp.commands[cmd](pp, args)
    - except KeyError:
    - printerr('\'%s\' command not found' % (cmd))
    + try:
    + pp.commands[cmd](pp, args)
    + except KeyError:
    + printerr('\'{}\' command not found'.format(cmd))
    if __name__ == '__main__':
    - # this is a work around when we're called for a directory that isn't the
    - # directory that this file is in. This happens during distcheck, as well
    - # as a few other cases that most people won't use ;)
    - if os.path.dirname(__file__) != '':
    - os.chdir(os.path.dirname(__file__))
    + # this is a work around when we're called for a directory that isn't the
    + # directory that this file is in. This happens during distcheck, as well
    + # as a few other cases that most people won't use ;)
    + if os.path.dirname(__file__) != '':
    + os.chdir(os.path.dirname(__file__))
    - main()
    + main()