From d1a5c99708fa5e2fc0387e31ccb57f004d74f2fc Mon Sep 17 00:00:00 2001
From: necoro <>
Date: Fri, 20 Jul 2007 07:19:27 +0000
Subject: new Plugin Scheme
---
plugin.xsd | 89 +++++++++++++++++++++++++
plugins/etc_proposals.xml | 28 ++++----
plugins/noroot.xml | 18 +++---
plugins/resume_loop.xml | 25 ++++---
plugins/shutdown.xml | 19 +++---
portato.py | 13 +++-
portato/constants.py | 19 ++++--
portato/plugin.py | 161 +++++++++++++++-------------------------------
setup.py | 4 +-
9 files changed, 214 insertions(+), 162 deletions(-)
create mode 100644 plugin.xsd
diff --git a/plugin.xsd b/plugin.xsd
new file mode 100644
index 0000000..7f9975b
--- /dev/null
+++ b/plugin.xsd
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/etc_proposals.xml b/plugins/etc_proposals.xml
index 8686072..410ce4b 100644
--- a/plugins/etc_proposals.xml
+++ b/plugins/etc_proposals.xml
@@ -1,17 +1,19 @@
-
-
+
+
+
+ René 'Necoro' Neumann
+ Etc-proposals plugin
+
portato.plugins.etc_proposals
-
-
-
+
+
+
+
+
+
+
-
diff --git a/plugins/noroot.xml b/plugins/noroot.xml
index 7e744ef..850a039 100644
--- a/plugins/noroot.xml
+++ b/plugins/noroot.xml
@@ -1,12 +1,12 @@
-
-
+
+
+ René 'Necoro' Neumann
+ No Root
portato.plugins.noroot
-
-
-
+
+
+
+
+
diff --git a/plugins/resume_loop.xml b/plugins/resume_loop.xml
index 572ccfa..14575cd 100644
--- a/plugins/resume_loop.xml
+++ b/plugins/resume_loop.xml
@@ -1,22 +1,21 @@
-
+
+ René 'Necoro' Neumann
+ Emerge Resume Loop
portato.plugins.resume_loop
-
-
-
+
+
+
+
-
- *
-
+
+ *
+
+
+
diff --git a/plugins/shutdown.xml b/plugins/shutdown.xml
index 586b57d..75323b1 100644
--- a/plugins/shutdown.xml
+++ b/plugins/shutdown.xml
@@ -1,17 +1,16 @@
-
-
+
+
+ René 'Necoro' Neumann
+ Shutdown
portato.plugins.shutdown
-
- *
-
+
+
+ *
+
+
-
diff --git a/portato.py b/portato.py
index e4210bb..5e8b30a 100755
--- a/portato.py
+++ b/portato.py
@@ -12,7 +12,7 @@
#
# Written by René 'Necoro' Neumann
-from portato.constants import VERSION, FRONTENDS, STD_FRONTEND
+from portato.constants import VERSION, FRONTENDS, STD_FRONTEND, XSD_LOCATION
from optparse import OptionParser
import sys
@@ -37,6 +37,9 @@ def main ():
parser.add_option("-e", "--ebuild", action = "store", dest = "ebuild",
help = "opens the ebuild viewer instead of launching Portato")
+ parser.add_option("-x", "--validate", action = "store", dest = "validate", metavar="PLUGIN",
+ help = "validates the given plugin xml instead of launching Portato")
+
# run parser
(options, args) = parser.parse_args()
@@ -62,6 +65,14 @@ def main ():
if options.ebuild:
show_ebuild(options.ebuild)
+ elif options.validate:
+ from lxml import etree
+ if etree.XMLSchema(file = XSD_LOCATION).validate(etree.parse(options.validate)):
+ print "Passed validation."
+ return
+ else:
+ print "Verification failed."
+ sys.exit(3)
else:
run()
diff --git a/portato/constants.py b/portato/constants.py
index f8da545..c17ee24 100644
--- a/portato/constants.py
+++ b/portato/constants.py
@@ -14,6 +14,8 @@
Constants used through out the program. Mainly different pathes.
These should be set during the installation.
+@var VERSION: the current version
+@type VERSION: string
@var CONFIG_DIR: The configuration directory.
@type CONFIG_DIR: string
@var CONFIG_LOCATION: L{CONFIG_DIR} plus name of the config file.
@@ -22,8 +24,10 @@ These should be set during the installation.
@type DATA_DIR: string
@var PLUGIN_DIR: Directory containing the plugin xmls.
@type PLUGIN_DIR: string
-@var VERSION: the current version
-@type VERSION: string
+@var XSD_DIR: Directory containing the plugin-xml schema.
+@type XSD_DIR: string
+@var XSD_LOCATION: Path of the plugin schema.
+@type XSD_LOCATION: string
@var ICON_DIR: directory containing the icons
@type ICON_DIR: string
@var APP_ICON: the path of the application icon
@@ -33,16 +37,21 @@ These should be set during the installation.
@var STD_FRONTEND: the frontend uses as the default, i.e. if no other one is given on the cmdline
@type STD_FRONTEND: string
"""
+from os.path import join as pjoin
+
+VERSION = "9999"
CONFIG_DIR = "/etc/portato/"
-CONFIG_LOCATION = CONFIG_DIR+"portato.cfg"
+CONFIG_LOCATION = pjoin(CONFIG_DIR, "portato.cfg")
DATA_DIR = "portato/gui/templates/"
PLUGIN_DIR = "plugins/"
-VERSION = "9999"
+
+XSD_DIR = "./"
+XSD_LOCATION = pjoin(XSD_DIR, "plugin.xsd")
ICON_DIR = "icons/"
-APP_ICON = ICON_DIR+"/portato-icon.png"
+APP_ICON = pjoin(ICON_DIR, "portato-icon.png")
FRONTENDS = ["gtk" ,"qt"]
STD_FRONTEND = "gtk"
diff --git a/portato/plugin.py b/portato/plugin.py
index a833696..06ef135 100644
--- a/portato/plugin.py
+++ b/portato/plugin.py
@@ -14,11 +14,12 @@
import os, os.path
from xml.dom.minidom import parse
+from lxml import etree
-from constants import PLUGIN_DIR
+from constants import PLUGIN_DIR, XSD_LOCATION
from helper import *
-class ParseException (Exception):
+class PluginImportException (ImportError):
pass
class Options (object):
@@ -36,21 +37,10 @@ class Options (object):
def parse (self, options):
for opt in options:
- if opt.hasChildNodes():
- nodes = opt.childNodes
-
- if len(nodes) > 1:
- raise ParseException, "Malformed option"
-
- if nodes[0].nodeType != nodes[0].TEXT_NODE:
- raise ParseException, "Malformed option"
-
- type = str(nodes[0].nodeValue.strip())
-
- if type in self.__options:
- self.set(type, True)
- else:
- raise ParseException, "Malformed option"
+ nodes = opt.childNodes
+ type = str(nodes[0].nodeValue.strip())
+ if type in self.__options:
+ self.set(type, True)
def get (self, name):
return self.__getattribute__(name)
@@ -70,13 +60,7 @@ class Menu:
@param call: the function to call relative to the import statement
@type call: string
- @raises ParseException: on parsing errors"""
-
- if not label:
- raise ParseException, "label attribute missing"
-
- if not call:
- raise ParseException, "call attribute missing"
+ @raises PluginImportException: if the plugin's import could not be imported"""
self.label = label
self.plugin = plugin
@@ -86,17 +70,17 @@ class Menu:
try:
mod = __import__(imp, globals(), locals(), [call])
except ImportError:
- raise ParseException, imp+" cannot be imported"
+ raise PluginImportException, imp
try:
self.call = eval("mod."+call) # build function
except AttributeError:
- raise ParseException, call+" cannot be imported"
+ raise PluginImportException, imp
else:
try:
self.call = eval(call)
except AttributeError:
- raise ParseException, call+" cannot be imported"
+ raise PluginImportException, imp
class Connect:
"""A single -element."""
@@ -109,12 +93,7 @@ class Connect:
@param type: the type of the connect ("before", "after", "override")
@type type: string
@param depend_plugin: a plugin we are dependant on
- @type depend_plugin: string or None
-
- @raises ParseException: on parsing errors"""
-
- if not type in ["before", "after", "override"]:
- raise ParseException, "Unknown connect type %s" % type
+ @type depend_plugin: string or None"""
self.type = type
self.hook = hook
@@ -140,16 +119,8 @@ class Hook:
@param hook: the hook to add to
@type hook: string
@param call: the call to make
- @type call: string
-
- @raises ParseException: on parsing errors"""
-
- if not hook:
- raise ParseException, "hook attribute missing"
+ @type call: string"""
- if not call:
- raise ParseException, "call attribute missing"
-
self.plugin = plugin
self.hook = hook
self.call = call
@@ -159,13 +130,8 @@ class Hook:
"""This gets a list of -elements and parses them.
@param connects: the list of 's
- @type connects: NodeList
-
- @raises ParseException: on parsing errors"""
+ @type connects: NodeList"""
- if not connects:
- raise ParseException, "No connect elements in hook"
-
for c in connects:
type = c.getAttribute("type")
if type == '':
@@ -175,12 +141,6 @@ class Hook:
dep_plugin = None
if c.hasChildNodes():
nodes = c.childNodes
- if len(nodes) > 1:
- raise ParseException, "Malformed connect"
-
- if nodes[0].nodeType != nodes[0].TEXT_NODE:
- raise ParseException, "Malformed connect"
-
dep_plugin = nodes[0].nodeValue.strip()
connect = Connect(self, type, dep_plugin)
@@ -195,42 +155,39 @@ class Plugin:
@param file: the file name of the plugin.xml
@type file: string
@param name: the name of the plugin
- @type name: string
+ @type name: Node
@param author: the author of the plugin
- @type author: string"""
+ @type author: Node"""
self.file = file
- self.name = name
- self.author = author
+ self.name = name.firstChild.nodeValue.strip()
+ self.author = author.firstChild.nodeValue.strip()
self._import = None
self.hooks = []
self.menus = []
self.options = Options()
def parse_hooks (self, hooks):
- """Gets a list of -elements and parses them.
+ """Gets an -elements and parses it.
- @param hooks: the list of elements
- @type hooks: NodeList
-
- @raises ParseException: on parsing errors"""
+ @param hooks: the hooks node
+ @type hooks: Node"""
- for h in hooks:
- hook = Hook(self, str(h.getAttribute("hook")), str(h.getAttribute("call")))
+ for h in hooks.getElementsByTagName("hook"):
+ hook = Hook(self, str(h.getAttribute("type")), str(h.getAttribute("call")))
hook.parse_connects(h.getElementsByTagName("connect"))
self.hooks.append(hook)
def parse_menus (self, menus):
- """Gets a list of