pidgin/purple-plugin-pack

Parents 97bea2885806
Children f3a36b4938cd
We stopped using plugin_pack.py awhile ago, so lets delete it finally
  • +0 -1
    .hgignore
  • +0 -615
    plugin_pack.py
  • --- a/.hgignore Sat Nov 24 08:25:38 2018 +0000
    +++ b/.hgignore Sun Mar 01 17:32:47 2020 -0600
    @@ -8,7 +8,6 @@
    buddytime/gtktimezonetest
    buddytime/recursetest
    build.*/
    -^plugin_pack\.(list|m4|stats)$
    po/missing
    po/notexist
    po/POTFILES$
    --- a/plugin_pack.py Sat Nov 24 08:25:38 2018 +0000
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,615 +0,0 @@
    -#!/usr/bin/python
    -
    -# plugin_pack.py - Helper script for obtaining info about the plugin pack
    -# Copyright (C) 2008 Gary Kramlich <grim@reaperworld.com>
    -#
    -# This program is free software; you can redistribute it and/or
    -# modify it under the terms of the GNU General Public License
    -# as published by the Free Software Foundation; either version 2
    -# of the License, or (at your option) any later version.
    -#
    -# This program is distributed in the hope that it will be useful,
    -# but WITHOUT ANY WARRANTY; without even the implied warranty of
    -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    -# GNU General Public License for more details.
    -#
    -# You should have received a copy of the GNU General Public License
    -# along with this program; if not, write to the Free Software
    -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
    -
    -"""Usage: plugin_pack.py [OPTION...] command
    -
    -Flags:
    -
    - -a Load abusive plugins
    - -d Load default plugins
    - -i Load incomplate plugins
    -
    - -f Load finch plugins
    - -p Load purple plugins
    - -P Load pidgin plugins
    -
    -Commands:
    -"""
    -
    -from __future__ import print_function
    -
    -import getopt
    -import glob
    -import os.path
    -import sys
    -
    -try:
    - import configparser
    -except ImportError:
    - import ConfigParser as configparser
    -
    -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 = ''
    - purple3 = True
    -
    - def __init__(self, directory, name, parser):
    - self.name = name
    -
    - 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')
    -
    - if parser.has_option(name, 'notes'):
    - self.notes = parser.get(name, 'notes')
    -
    - if parser.has_option(name, 'purple3'):
    - self.purple3 = parser.get(name, 'purple3') != 'no'
    -
    - 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: {}\n'.format(self.name)
    - output += 'authors: {}\n'.format(', '.join(self.authors))
    - output += 'type: {}\n'.format(self.type)
    - output += 'depends: {}\n'.format(' '.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: {}\n'.format(self.notes)
    -
    - if not self.purple3:
    - output += 'purple3: no\n'
    -
    - return output
    -
    - def __lt__(self, other):
    - return self.name < other.name
    -
    -
    -class PluginPack:
    - commands = {}
    - plugins = {}
    -
    - def load_plugins(self, types, depends, purple_ver=2):
    - if len(types) == 0:
    - types = None
    -
    - if len(depends) == 0:
    - depends = None
    -
    - for file in glob.glob('*/plugins.cfg'):
    - parser = configparser.ConfigParser()
    -
    - 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)
    -
    - # 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
    -
    - if purple_ver == 3 and not p.purple3:
    - continue
    -
    - self.plugins[p.provides] = p
    -
    - def list_type(self, type):
    - list = []
    -
    - for name in self.plugins.keys():
    - plugin = self.plugins[name]
    - if plugin.type == type:
    - list.append(plugin)
    -
    - list.sort()
    -
    - return list
    -
    - def list_dep(self, dep):
    - list = []
    -
    - for name in self.plugins.keys():
    - plugin = self.plugins[name]
    -
    - if dep in plugin.depends:
    - list.append(plugin)
    -
    - list.sort()
    -
    - return list
    -
    - def print_names(self, list):
    - names = []
    -
    - for plugin in list:
    - names.append(plugin.name)
    -
    - print(','.join(names))
    -
    - def default_plugins(self):
    - return self.list_type('default')
    -
    - def abusive_plugins(self):
    - return self.list_type('abusive')
    -
    - def incomplete_plugins(self):
    - return self.list_type('incomplete')
    -
    - def purple_plugins(self):
    - return self.list_dep('purple')
    -
    - def finch_plugins(self):
    - return self.list_dep('finch')
    -
    - def pidgin_plugins(self):
    - return self.list_dep('pidgin')
    -
    - def unique_dirs(self):
    - dirs = {}
    - for name in self.plugins.keys():
    - dirs[self.plugins[name].directory] = 1
    -
    - dirs = sorted(dirs.keys())
    -
    - return 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:')
    -
    - cmds = self.commands.keys()
    - cmds.remove('help')
    - cmds.sort()
    - print(' {}'.format(' '.join(cmds)))
    - commands['help'] = help
    -
    - def dist_dirs(self, args):
    - """Displays a list of all plugin directories to included in the distribution"""
    - print(' '.join(self.unique_dirs()))
    - commands['dist_dirs'] = dist_dirs
    -
    - 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)
    -
    - # store the external depedencies
    - externals = args[0].split(',')
    -
    - deps = {}
    -
    - # 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
    -
    - # 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)
    -
    - check += defaults
    -
    - continue
    -
    - 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)
    -
    - # create our list of plugins to build
    - build = []
    -
    - # 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
    -
    - # 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
    -
    - if count == 0:
    - return False
    - else:
    - if not has_deps(dep):
    - return False
    -
    - # make sure the provides isn't an external
    - if not provides in externals:
    - build.append(provides)
    -
    - # everything checks out!
    - return True
    -
    - # 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 = []
    -
    - for provides in build:
    - plugin = self.plugins[provides]
    -
    - output.append(plugin.directory)
    -
    - output.sort()
    -
    - print("{}".format(','.join(output)))
    - commands['build_dirs'] = build_dirs
    -
    - def list_plugins(self, args):
    - """Displays a list similiar to 'dpkg -l' about the plugin pack"""
    -
    - data = {}
    -
    - # 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]
    -
    - 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'
    -
    - if 'finch' in plugin.depends:
    - ui = 'f'
    - elif 'pidgin' in plugin.depends:
    - ui = 'p'
    - elif 'purple' in plugin.depends:
    - ui = 'r'
    - else:
    - ui = 'u'
    -
    - widths[0] = max(widths[0], len(plugin.name))
    - widths[1] = max(widths[1], len(plugin.provides))
    - widths[2] = max(widths[2], len(plugin.summary))
    -
    - data[plugin.provides] = [type, ui, plugin.name, plugin.provides, plugin.summary]
    -
    - 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])))
    -
    - # create the format var
    - fmt = '{}{} {:<' + str(widths[0]) + '} {:<' + str(widths[1]) + '} {}'
    -
    - # now loop through the list again, with everything formatted
    - keys = sorted(list(data.keys()))
    -
    - for p in keys:
    - 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
    -
    - # 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'))
    -
    - # 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')
    -
    - # 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 $PURPLE_VER 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 $PURPLE_VER show_names $PP_BUILD"',
    - 'PP_PIDGIN_BUILD="$PYTHON $srcdir/plugin_pack.py -P $PURPLE_VER show_names $PP_BUILD"',
    - 'PP_FINCH_BUILD="$PYTHON $srcdir/plugin_pack.py -f $PURPLE_VER show_names $PP_BUILD"'))
    - commands['config_file'] = config_file
    -
    - 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{}[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 default plugins
    - print('{}\n{}'.format('\t/* default plugins */',
    - '\tnode[fillcolor="palegreen",shape="tab"];'))
    - print_plugins(self.default_plugins())
    - print('')
    -
    - # run through the incomplete plugins
    - print('{}\n{}'.format('\t/* incomplete plugins */',
    - '\tnode[fillcolor="lightyellow1",shape="note"];'))
    - print_plugins(self.incomplete_plugins())
    - print('')
    -
    - # run through the abusive plugins
    - print('{}\n{}'.format('\t/* abusive plugins */',
    - '\tnode[fillcolor="lightpink",shape="octagon"];'))
    - print_plugins(self.abusive_plugins())
    - print('')
    -
    - # 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"];'))
    -
    - for name in self.plugins.keys():
    - plugin = self.plugins[name]
    -
    - node, label = node_label(plugin)
    -
    - for dep in plugin.depends:
    - dep = dep.replace('-', '_')
    - print('\t() -> {};'.format(node, dep))
    -
    - print('}')
    - commands['dependency_graph'] = dependency_graph
    -
    - 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))
    -
    - print(' .\n .\n Homepage: {}'.format(WEBPAGE))
    - commands['debian_description'] = debian_description
    -
    - def show_names(self, args):
    - """Displays the names of the given comma separated list of provides"""
    -
    - if len(args) == 0 or len(args[0]) == 0:
    - printerr('show_names expects a comma separated list of provides')
    - sys.exit(1)
    -
    - provides = args[0].split(',')
    - if len(provides) == 0:
    - print("none")
    -
    - line = " "
    -
    - for provide in provides:
    - if not provide in self.plugins:
    - continue
    -
    - name = self.plugins[provide].name
    -
    - if len(line) + len(name) + 2 > 75:
    - print(line.rstrip(','))
    - line = ' '
    -
    - line += ' {},'.format(name)
    -
    - if len(line) > 1:
    - print(line.rstrip(','))
    - commands['show_names'] = show_names
    -
    - 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
    -
    - 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__)
    -
    - cmds = sorted(list(pp.commands.keys()))
    -
    - for cmd in cmds:
    - print(" {:20} {}".format(cmd, pp.commands[cmd].__doc__))
    -
    - print("")
    -
    - sys.exit(exitcode)
    -
    -def main():
    - # create our main instance
    - pp = PluginPack()
    -
    - types = []
    - depends = []
    - purple_ver = 2
    -
    - try:
    - shortopts = 'adfiPp23'
    -
    - 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')
    - elif o == '-2':
    - purple_ver = 2
    - elif o == '-3':
    - purple_ver = 3
    -
    - # load the plugins that have been requested, if both lists are empty, all
    - # plugins are loaded
    - pp.load_plugins(types, depends, purple_ver)
    -
    - if(len(args) == 0):
    - show_usage(pp, 1)
    -
    - cmd = args[0]
    - args = args[1:]
    -
    - 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__))
    -
    - main()
    -