123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- # -*- coding: utf-8 -*-
-
- import imp
- import os
- import sys
-
- import yaml
-
-
- class PluginError(Exception):
- pass
-
-
- class PluginUsageError(PluginError):
- pass
-
-
- class ConfigError(Exception):
-
- def __init__(self, path, key):
- self.path = path
- self.key = key
-
- def __str__(self):
- return "invalid key: %r in %s" % (self.key, self.path)
-
-
- class Config(object):
-
- def __init__(self, paths, valid_keys):
- self._valid_keys = valid_keys
- for path in paths:
- self.load(path)
-
- def __str__(self):
- ss = [" %s: %s" % (vk, getattr(self, vk))
- for vk in self._valid_keys]
- return "\n".join(ss)
-
- def load(self, path):
- try:
- with open(path) as fh:
- conf = yaml.load(fh)
- except IOError:
- pass
- else:
- for key in conf.keys():
- if key in self._valid_keys:
- setattr(self, key, conf[key])
- else:
- raise ConfigError(path, key)
-
-
- class XGPRenderer(object):
-
- def __init__(self, txt=None):
- self.txt = txt
- self.img = None
- self.tool = txt
- self.bar = None
- self.click = None
- self._fields = ['txt', 'img', 'tool', 'bar', 'click']
-
- def __str__(self):
- out = ""
- for field in self._fields:
- value = getattr(self, field, None)
- if value is not None:
- out += "<%(f)s>%(v)s</%(f)s>" % {'f': field, 'v': value}
- return out
-
-
- class BasePlugin(object):
-
- def __init__(self, data):
- self.data = data
-
- def render(self):
- method_n = "render_" + self.data.fmt
-
- def ex(__):
- raise PluginError("plugin method not defined: " + method_n)
-
- render_fn = getattr(self, method_n, ex)
- return render_fn()
-
- def render_xgp(self):
- return XGPRenderer(self.render_plain())
-
-
- class PluginData(object):
-
- def __init__(self, cmdargs):
- self.args = []
- self.fmt = "plain"
- self.maxlen = 40
- self.name = ""
- self._load(cmdargs)
-
- def _load(self, cmdargs):
- if cmdargs['--plain']:
- self.fmt = "plain"
- elif cmdargs['--xgp']:
- self.fmt = "xgp"
- self.name = cmdargs['COMMAND']
- self.args = cmdargs['ARGS']
- if cmdargs['--chars']:
- self.maxlen = int(cmdargs['--chars'])
-
-
- class Subcommand(object):
-
- def __init__(self, cmdargs, pluginpath):
- self.plugindata = PluginData(cmdargs)
- self.name = cmdargs['COMMAND']
- self._load_plugin(pluginpath)
-
- def _load_plugin(self, pluginpath):
- modpath = "%s/%s.py" % (pluginpath, self.name)
- try:
- with open(modpath) as fh:
- module = imp.load_module(self.name, fh, modpath,
- (".py", "r", imp.PY_SOURCE))
- except IOError:
- raise PluginError("no such plugin: %s" % self.name)
- self.plugin = module.Plugin(self.plugindata)
-
- def _format_output(self, raw):
- suffix = u'…'
- cooked = raw.decode("utf-8")
- if self.plugindata.fmt == "plain":
- if self.plugindata.maxlen and len(raw) > self.plugindata.maxlen:
- newlen = self.plugindata.maxlen - len(suffix)
- cooked = cooked[:newlen] + suffix
- return cooked.encode("utf-8")
-
- def get_output(self):
- return self._format_output(self.plugin.render())
-
-
- class App:
-
- name = "sardine"
-
- cfg_paths = [
- '/etc/sardine/config',
- '%(HOME)s/.config/sardine/config' % os.environ,
- '.sardine.config'
- ]
-
- cfg_valid_keys = [
- ]
-
- def __init__(self, cmdargs):
- self.cmdargs = cmdargs
- self._set_pluginpath()
- self.config = Config(self.cfg_paths, self.cfg_valid_keys)
-
- def _set_pluginpath(self):
- mypath = os.path.dirname(os.path.realpath(sys.argv[0]))
- path = mypath + "/plugins"
- path = os.environ.get("SARDINE_PLUGINS", path)
- self.pluginpath = path
-
- def die(self, msg, rv=9):
- sys.stderr.write("%s\n" % msg)
- self.exit(rv)
-
- def exit(self, rv=0):
- sys.exit(rv)
-
- def run(self):
- try:
- self.subcommand = Subcommand(self.cmdargs, self.pluginpath)
- print self.subcommand.get_output()
- except PluginUsageError as e:
- msg = ("plugin usage: %s %s %s"
- % (self.name, self.subcommand.name, e))
- self.die(msg, 11)
- except PluginError as e:
- self.die(e, 10)
|