summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugin.xsd87
-rw-r--r--plugins/etc_proposals.py43
-rw-r--r--plugins/etc_proposals.xml19
-rw-r--r--plugins/gpytage.py27
-rw-r--r--plugins/gpytage.xml13
-rw-r--r--plugins/notify.py45
-rw-r--r--plugins/notify.xml13
-rwxr-xr-xportato.py19
-rw-r--r--portato/backend/portage/__init__.py12
-rw-r--r--portato/backend/portage/package.py9
-rw-r--r--portato/backend/portage/package_22.py (renamed from portato/plugins/gpytage.py)14
-rw-r--r--portato/backend/portage/settings_22.py27
-rw-r--r--portato/backend/portage/system.py13
-rw-r--r--portato/backend/portage/system_22.py34
-rw-r--r--portato/gui/dialogs.py7
-rw-r--r--portato/gui/windows/mailinfo.py30
-rw-r--r--portato/gui/windows/main.py19
-rw-r--r--portato/gui/windows/plugin.py5
-rw-r--r--portato/plugin.py636
-rw-r--r--portato/plugins/__init__.py7
-rw-r--r--portato/plugins/etc_proposals.py31
-rw-r--r--portato/plugins/notify.py22
-rw-r--r--setup.py5
23 files changed, 449 insertions, 688 deletions
diff --git a/plugin.xsd b/plugin.xsd
deleted file mode 100644
index 985b105..0000000
--- a/plugin.xsd
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://portato.sourceforge.net/plugin" targetNamespace="http://portato.sourceforge.net/plugin" elementFormDefault="qualified">
- <xs:element name="plugin">
- <xs:complexType>
- <xs:all>
- <xs:element name="name" type="string" />
- <xs:element name="author" type="string" />
- <xs:element name="import" type="importString" minOccurs="0"/>
- <xs:element name="dependencies" minOccurs="0">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="dependency" type="string" maxOccurs="unbounded" />
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="hooks" minOccurs="0">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="hook" minOccurs="1" maxOccurs="unbounded">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="connect" minOccurs="0" maxOccurs="unbounded">
- <xs:complexType>
- <xs:simpleContent>
- <xs:extension base="xs:string">
- <xs:attribute name="type" default="before">
- <xs:simpleType>
- <xs:restriction base="xs:string">
- <xs:enumeration value="before" />
- <xs:enumeration value="override" />
- <xs:enumeration value="after" />
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attribute name="type" type="string" use="required" />
- <xs:attribute name="call" type="functionCall" use="required" />
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="options" minOccurs="0">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="option" minOccurs="1" maxOccurs="unbounded" type="string" />
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- <xs:element name="menu" minOccurs="0">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="item" minOccurs="1" maxOccurs="unbounded">
- <xs:complexType>
- <xs:simpleContent>
- <xs:extension base="string">
- <xs:attribute name="call" type="functionCall" use="required" />
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- </xs:all>
- </xs:complexType>
- </xs:element>
- <xs:simpleType name="importString">
- <xs:restriction base="xs:string">
- <xs:pattern value="([a-zA-Z_]+\.?)+" />
- </xs:restriction>
- </xs:simpleType>
- <xs:simpleType name="functionCall">
- <xs:restriction base="xs:string">
- <xs:pattern value="[a-zA-Z_][0-9a-zA-Z_]*" />
- </xs:restriction>
- </xs:simpleType>
- <xs:simpleType name="string">
- <xs:restriction base="xs:string">
- <xs:minLength value="1" />
- </xs:restriction>
- </xs:simpleType>
-</xs:schema>
diff --git a/plugins/etc_proposals.py b/plugins/etc_proposals.py
new file mode 100644
index 0000000..07f9a80
--- /dev/null
+++ b/plugins/etc_proposals.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+#
+# File: plugins/etc_proposals.py
+# This file is part of the Portato-Project, a graphical portage-frontend.
+#
+# Copyright (C) 2007-2008 René 'Necoro' Neumann
+# This is free software. You may redistribute copies of it under the terms of
+# the GNU General Public License version 2.
+# There is NO WARRANTY, to the extent permitted by law.
+#
+# Written by René 'Necoro' Neumann <necoro@necoro.net>
+
+from portato.helper import error
+
+import os
+from subprocess import Popen
+
+class EtcProposals (Plugin):
+ __author__ = "René 'Necoro' Neumann"
+ __description__ = "Adds support for <b>etc-proposals</b>, a graphical etc-update replacement."
+ __dependency__ = ["app-portage/etc-proposals"]
+
+ def __init__ (self):
+ Plugin.__init__(self)
+
+ self.prog = ["/usr/sbin/etc-proposals"]
+ self.add_call("after_emerge", self.hook, type = "after")
+ self.add_menu("Et_c-Proposals", self.menu)
+
+ def launch (self, options = []):
+ if os.getuid() == 0:
+ Popen(self.prog+options)
+ else:
+ error("ETC_PROPOSALS :: %s",_("Cannot start etc-proposals. Not root!"))
+
+ def hook (self, *args, **kwargs):
+ """Entry point for this plugin."""
+ self.launch(["--fastexit"])
+
+ def menu (self, *args):
+ self.launch()
+
+register(EtcProposals)
diff --git a/plugins/etc_proposals.xml b/plugins/etc_proposals.xml
deleted file mode 100644
index 2caf341..0000000
--- a/plugins/etc_proposals.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<plugin xmlns="http://portato.sourceforge.net/plugin" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://portato.sourceforge.net/plugin http://portato.sourceforge.net/plugin.xsd">
-
- <author>René 'Necoro' Neumann</author>
- <name>Etc-proposals</name>
-
- <import>portato.plugins.etc_proposals</import>
-
- <hooks>
- <hook type = "after_emerge" call = "etc_prop">
- <connect type="after" />
- </hook>
- </hooks>
-
- <menu>
- <item call="etc_prop_menu">Et_c-Proposals</item>
- </menu>
-
-</plugin>
diff --git a/plugins/gpytage.py b/plugins/gpytage.py
new file mode 100644
index 0000000..33509e1
--- /dev/null
+++ b/plugins/gpytage.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+#
+# File: plugins/gpytage.py
+# This file is part of the Portato-Project, a graphical portage-frontend.
+#
+# Copyright (C) 2008 René 'Necoro' Neumann
+# This is free software. You may redistribute copies of it under the terms of
+# the GNU General Public License version 2.
+# There is NO WARRANTY, to the extent permitted by law.
+#
+# Written by René 'Necoro' Neumann <necoro@necoro.net>
+
+from subprocess import Popen
+
+class GPytage (Plugin):
+ __author__ = "René 'Necoro' Neumann"
+ __description__ = "Adds a menu entry to directly start <b>gpytage</b>, a config editor."
+ __dependency__ = ["app-portage/gpytage"]
+
+ def __init__ (self):
+ Plugin.__init__(self)
+ self.add_menu("Config _Editor", self.menu)
+
+ def menu (self, *args):
+ Popen(["/usr/bin/gpytage"])
+
+register(GPytage)
diff --git a/plugins/gpytage.xml b/plugins/gpytage.xml
deleted file mode 100644
index b203ae0..0000000
--- a/plugins/gpytage.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<plugin xmlns="http://portato.sourceforge.net/plugin" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://portato.sourceforge.net/plugin http://portato.sourceforge.net/plugin.xsd">
-
- <author>René 'Necoro' Neumann</author>
- <name>GPytage</name>
-
- <import>portato.plugins.gpytage</import>
-
- <menu>
- <item call="gpytage">Config _Editor</item>
- </menu>
-
-</plugin>
diff --git a/plugins/notify.py b/plugins/notify.py
new file mode 100644
index 0000000..bc1b2ea
--- /dev/null
+++ b/plugins/notify.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+#
+# File: plugins/notify.py
+# This file is part of the Portato-Project, a graphical portage-frontend.
+#
+# Copyright (C) 2007-2008 René 'Necoro' Neumann
+# This is free software. You may redistribute copies of it under the terms of
+# the GNU General Public License version 2.
+# There is NO WARRANTY, to the extent permitted by law.
+#
+# Written by René 'Necoro' Neumann <necoro@necoro.net>
+
+import pynotify
+
+from portato import get_listener
+
+from portato.helper import warning, error, debug
+from portato.constants import APP_ICON, APP
+
+class Notify (Plugin):
+ __author__ = "René 'Necoro' Neumann"
+ __description__ = "Show notifications when an emerge process finishes."
+ __dependency__ = ["dev-python/notify-python"]
+
+ def __init__ (self):
+ Plugin.__init__(self)
+ self.add_call("after_emerge", self.notify)
+
+ def notify (self, retcode, **kwargs):
+ if retcode is None:
+ warning("NOTIFY :: %s", _("Notify called while process is still running!"))
+ else:
+ icon = APP_ICON
+ if retcode == 0:
+ text = _("Emerge finished!")
+ descr = ""
+ urgency = pynotify.URGENCY_NORMAL
+ else:
+ text = _("Emerge failed!")
+ descr = _("Error Code: %d") % retcode
+ urgency = pynotify.URGENCY_CRITICAL
+
+ get_listener().send_notify(base = text, descr = descr, icon = icon, urgency = urgency)
+
+register(Notify)
diff --git a/plugins/notify.xml b/plugins/notify.xml
deleted file mode 100644
index 9a89987..0000000
--- a/plugins/notify.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<plugin xmlns="http://portato.sourceforge.net/plugin" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://portato.sourceforge.net/plugin http://portato.sourceforge.net/plugin.xsd">
-
- <author>René 'Necoro' Neumann</author>
- <name>Notify</name>
-
- <import>portato.plugins.notify</import>
-
- <hooks>
- <hook type = "after_emerge" call = "notify" />
- </hooks>
-
-</plugin>
diff --git a/portato.py b/portato.py
index a4f871a..69fb792 100755
--- a/portato.py
+++ b/portato.py
@@ -36,30 +36,13 @@ def main ():
parser.add_option("--shm", action = "store", nargs = 3, type="long", dest = "shm",
help = SUPPRESS_HELP)
- parser.add_option("-x", "--validate", action = "store", dest = "validate", metavar="PLUGIN",
- help = _("validates the given plugin xml instead of launching Portato"))
-
parser.add_option("-F", "--no-fork", "-L", action = "store_true", dest = "nofork", default = False,
help = _("do not fork off as root") + (" (%s)" % _("-L is deprecated")))
# run parser
(options, args) = parser.parse_args()
- if options.validate: # validate a plugin
- from lxml import etree
- try:
- etree.XMLSchema(file = XSD_LOCATION).assertValid(etree.parse(options.validate))
- except etree.XMLSyntaxError, e:
- print _("Validation failed. XML syntax error: %s.") % e[0]
- sys.exit(3)
- except etree.DocumentInvalid:
- print _("Validation failed. Does not comply with schema.")
- sys.exit(3)
- else:
- print _("Validation succeeded.")
- return
-
- elif options.nofork or os.getuid() == 0: # start GUI
+ if options.nofork or os.getuid() == 0: # start GUI
from portato.gui import run
from portato.helper import info
info("%s v. %s", _("Starting Portato"), VERSION)
diff --git a/portato/backend/portage/__init__.py b/portato/backend/portage/__init__.py
index 6ccbf7f..be6cce6 100644
--- a/portato/backend/portage/__init__.py
+++ b/portato/backend/portage/__init__.py
@@ -12,5 +12,13 @@
from __future__ import absolute_import
-from .system import PortageSystem
-from .package import PortagePackage
+from portage import VERSION as PV
+
+VERSION = tuple(map(int, (x.split("_")[0] for x in PV.split("."))))
+
+if VERSION >= (2, 2):
+ from .system_22 import PortageSystem_22 as PortageSystem
+ from .package_22 import PortagePackage_22 as PortagePackage
+else:
+ from .system import PortageSystem
+ from .package import PortagePackage
diff --git a/portato/backend/portage/package.py b/portato/backend/portage/package.py
index 3502306..78125ee 100644
--- a/portato/backend/portage/package.py
+++ b/portato/backend/portage/package.py
@@ -18,7 +18,12 @@ from .. import system
from ..exceptions import BlockedException, PackageNotFoundException, DependencyCalcError
from ...helper import debug, error, unique_array
-import portage, portage_dep
+import portage
+
+try:
+ import portage.dep as portage_dep
+except ImportError:
+ import portage_dep
import os.path
@@ -221,7 +226,7 @@ class PortagePackage (Package):
for dep in deps:
if dep[0] == '!': # blocking sth
- blocked = system.find_packages(dep, "installed", only_cpv = True)
+ blocked = system.find_packages(dep, "installed")
if len(blocked) == 1: # only exact one match allowed to be harmless
if blocked[0].get_slot_cp() == self.get_slot_cp(): # blocks in the same slot are harmless
continue
diff --git a/portato/plugins/gpytage.py b/portato/backend/portage/package_22.py
index 22cc7ef..4fe03d9 100644
--- a/portato/plugins/gpytage.py
+++ b/portato/backend/portage/package_22.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
-# File: portato/plugins/gpytage.py
+# File: portato/backend/portage/package_22.py
# This file is part of the Portato-Project, a graphical portage-frontend.
#
# Copyright (C) 2008 René 'Necoro' Neumann
@@ -10,7 +10,13 @@
#
# Written by René 'Necoro' Neumann <necoro@necoro.net>
-from subprocess import Popen
+from __future__ import absolute_import, with_statement
-def gpytage(*args, **kwargs):
- Popen(["/usr/bin/gpytage"])
+from .package import PortagePackage
+
+class PortagePackage_22 (PortagePackage):
+ """
+ The 2.2 specialization of the portage package.
+ Currently this is identical to the normal one.
+ """
+ pass
diff --git a/portato/backend/portage/settings_22.py b/portato/backend/portage/settings_22.py
new file mode 100644
index 0000000..a43d69e
--- /dev/null
+++ b/portato/backend/portage/settings_22.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+#
+# File: portato/backend/portage/settings_22.py
+# This file is part of the Portato-Project, a graphical portage-frontend.
+#
+# Copyright (C) 2008 René 'Necoro' Neumann
+# This is free software. You may redistribute copies of it under the terms of
+# the GNU General Public License version 2.
+# There is NO WARRANTY, to the extent permitted by law.
+#
+# Written by René 'Necoro' Neumann <necoro@necoro.net>
+
+from __future__ import absolute_import
+
+import portage.sets
+from .settings import PortageSettings
+
+class PortageSettings_22 (PortageSettings):
+ """Enhances the normal PortageSettings in ways, that it adds the setsconfig."""
+
+ def __init__ (self):
+ PortageSettings.__init__(self)
+
+ def load (self):
+ PortageSettings.load(self)
+
+ self.setsconfig = portage.sets.load_default_config(self.settings, self.trees[self.settings["ROOT"]])
diff --git a/portato/backend/portage/system.py b/portato/backend/portage/system.py
index 0d81945..feaf4df 100644
--- a/portato/backend/portage/system.py
+++ b/portato/backend/portage/system.py
@@ -16,6 +16,7 @@ import re, os, os.path
import portage
from collections import defaultdict
+from . import VERSION
from .package import PortagePackage
from .settings import PortageSettings
from ..system_interface import SystemInterface
@@ -36,8 +37,6 @@ class PortageSystem (SystemInterface):
self.use_descs = {}
self.local_use_descs = defaultdict(dict)
- self._version = tuple([x.split("_")[0] for x in portage.VERSION.split(".")])
-
def get_version (self):
return "Portage %s" % portage.VERSION
@@ -142,7 +141,7 @@ class PortageSystem (SystemInterface):
"""
if not only_cpv:
- return [PortagePackage(x) for x in list_of_packages]
+ return [self.new_package(x) for x in list_of_packages]
else:
return list_of_packages
@@ -154,7 +153,7 @@ class PortageSystem (SystemInterface):
if only_cpv:
return portage.best(list)
else:
- return PortagePackage(portage.best(list))
+ return self.new_package(portage.best(list))
def find_best_match (self, search_key, masked = False, only_installed = False, only_cpv = False):
t = []
@@ -166,7 +165,7 @@ class PortageSystem (SystemInterface):
t = self.find_packages(search_key, pkgSet = pkgSet, masked = masked, with_version = True, only_cpv = True)
- if self._version >= (2,1,5):
+ if VERSION >= (2,1,5):
t += [pkg.get_cpv() for pkg in self.find_packages(search_key, "installed") if not (pkg.is_testing(True) or pkg.is_masked())]
else:
t = self.find_packages(search_key, "installed", only_cpv=True)
@@ -287,7 +286,7 @@ class PortageSystem (SystemInterface):
unresolved = []
for x in list:
cpv = x.strip()
- if len(cpv) and check(cpv):
+ if cpv and check(cpv):
pkg = self.find_best_match(cpv, only_cpv = only_cpv)
if pkg:
resolved.append(pkg)
@@ -304,7 +303,7 @@ class PortageSystem (SystemInterface):
return portage.catpkgsplit(cpv)
def sort_package_list(self, pkglist):
- pkglist.sort(PortagePackage.compare_version)
+ pkglist.sort(PortagePackage.compare_version) # XXX: waaah ... direct package naming... =/
return pkglist
def reload_settings (self):
diff --git a/portato/backend/portage/system_22.py b/portato/backend/portage/system_22.py
new file mode 100644
index 0000000..be27186
--- /dev/null
+++ b/portato/backend/portage/system_22.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+#
+# File: portato/backend/portage/system_22.py
+# This file is part of the Portato-Project, a graphical portage-frontend.
+#
+# Copyright (C) 2008 René 'Necoro' Neumann
+# This is free software. You may redistribute copies of it under the terms of
+# the GNU General Public License version 2.
+# There is NO WARRANTY, to the extent permitted by law.
+#
+# Written by René 'Necoro' Neumann <necoro@necoro.net>
+
+from __future__ import absolute_import, with_statement
+
+import os
+import portage
+
+from collections import defaultdict
+
+from .package_22 import PortagePackage_22
+from .settings_22 import PortageSettings_22
+from .system import PortageSystem
+
+class PortageSystem_22 (PortageSystem):
+
+ def __init__ (self):
+ self.settings = PortageSettings_22()
+ portage.WORLD_FILE = os.path.join(self.settings.settings["ROOT"],portage.WORLD_FILE)
+
+ self.use_descs = {}
+ self.local_use_descs = defaultdict(dict)
+
+ def new_package (self, cpv):
+ return PortagePackage_22(cpv)
diff --git a/portato/gui/dialogs.py b/portato/gui/dialogs.py
index 8f0c78c..7f8a736 100644
--- a/portato/gui/dialogs.py
+++ b/portato/gui/dialogs.py
@@ -13,6 +13,13 @@
import gtk
from ..helper import error
+def mail_failure_dialog(e):
+ dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, _("Mail could not be sent"))
+ dialog.format_secondary_text(_("The error was: %s") % e)
+ ret = dialog.run()
+ dialog.destroy()
+ return ret
+
def queue_not_empty_dialog():
dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_NONE, _("There are some packages in the emerge queue and/or an emerge process is running.\nDo you really want to quit?"))
#dialog.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_YES, gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
diff --git a/portato/gui/windows/mailinfo.py b/portato/gui/windows/mailinfo.py
index 8e476c6..1b5735a 100644
--- a/portato/gui/windows/mailinfo.py
+++ b/portato/gui/windows/mailinfo.py
@@ -12,11 +12,12 @@
from __future__ import absolute_import
-import smtplib
+import smtplib, socket
import time
from .basic import AbstractDialog
from ..utils import GtkThread
+from ..dialogs import mail_failure_dialog
from ...helper import debug, info
from ...constants import VERSION
@@ -59,20 +60,23 @@ Subject: %s
self.message = message
def send (self):
- debug("Connecting to server")
- server = smtplib.SMTP("mail.necoro.eu")
- debug("Sending mail")
try:
+ debug("Connecting to server")
+ server = smtplib.SMTP("mail.necoro.eu")
+ debug("Sending mail")
try:
- server.sendmail(self.addr, self.TO, self.message)
- except smtplib.SMTPRecipientsRefused, e:
- info(_("An error occurred while sending. I think we where greylisted. The error: %s") % e)
- info(_("Wait 60 seconds and try again."))
- time.sleep(60)
- server.sendmail(self.addr, self.TO, self.message)
- debug("Sent")
- finally:
- server.quit()
+ try:
+ server.sendmail(self.addr, self.TO, self.message)
+ except smtplib.SMTPRecipientsRefused, e:
+ info(_("An error occurred while sending. I think we where greylisted. The error: %s") % e)
+ info(_("Wait 60 seconds and try again."))
+ time.sleep(60)
+ server.sendmail(self.addr, self.TO, self.message)
+ debug("Sent")
+ finally:
+ server.quit()
+ except socket.error, e:
+ mail_failure_dialog("%s (Code: %s)" % (e.args[1], e.args[0]))
def cb_cancel_clicked (self, *args):
diff --git a/portato/gui/windows/main.py b/portato/gui/windows/main.py
index 364810d..b4e6353 100644
--- a/portato/gui/windows/main.py
+++ b/portato/gui/windows/main.py
@@ -607,13 +607,13 @@ class MainWindow (Window):
# set plugins and plugin-menu
splash(_("Loading Plugins"))
- plugin.load_plugins("gtk")
- menus = plugin.get_plugin_queue().get_plugin_menus()
+ plugin.load_plugins()
+ menus = [p.menus for p in plugin.get_plugin_queue().get_plugins()]
if menus:
self.tree.get_widget("pluginMenuItem").set_no_show_all(False)
pluginMenu = self.tree.get_widget("pluginMenu")
- for m in menus:
+ for m in itt.chain(*menus):
item = gtk.MenuItem(m.label)
item.connect("activate", m.call)
pluginMenu.append(item)
@@ -1082,13 +1082,8 @@ class MainWindow (Window):
def save_plugin (p):
def _save ():
- stat_on = p.status >= p.STAT_ENABLED
- hard_on = not p.get_option("disabled")
-
- if stat_on != hard_on:
- return int(stat_on)
- else:
- return ""
+ return int(p.status >= p.STAT_ENABLED)
+
return _save
# SESSION VERSION
@@ -1553,8 +1548,8 @@ class MainWindow (Window):
if queue is None:
plugins = []
else:
- plugins = queue.get_plugins()
-
+ plugins = list(queue.get_plugins())
+
PluginWindow(self.window, plugins)
return True
diff --git a/portato/gui/windows/plugin.py b/portato/gui/windows/plugin.py
index 17c5326..9760658 100644
--- a/portato/gui/windows/plugin.py
+++ b/portato/gui/windows/plugin.py
@@ -15,6 +15,7 @@ from __future__ import absolute_import
import gtk
from .basic import AbstractDialog
+from ...backend import system
from ...helper import debug
class PluginWindow (AbstractDialog):
@@ -64,7 +65,7 @@ class PluginWindow (AbstractDialog):
self.window.show_all()
def build_dep_list (self):
- store = gtk.TreeStore(gtk.gdk.Pixbuf, str)
+ store = gtk.ListStore(gtk.gdk.Pixbuf, str)
self.depList.set_model(store)
@@ -113,7 +114,7 @@ class PluginWindow (AbstractDialog):
if not plugin.description:
self.descrLabel.hide()
else:
- self.descrLabel.set_label(plugin.description)
+ self.descrLabel.set_markup(plugin.description)
self.descrLabel.show()
self.authorLabel.set_label(plugin.author)
diff --git a/portato/plugin.py b/portato/plugin.py
index cbadfd1..7b8a493 100644
--- a/portato/plugin.py
+++ b/portato/plugin.py
@@ -3,371 +3,183 @@
# File: portato/plugin.py
# This file is part of the Portato-Project, a graphical portage-frontend.
#
-# Copyright (C) 2007 René 'Necoro' Neumann
+# Copyright (C) 2008 René 'Necoro' Neumann
# This is free software. You may redistribute copies of it under the terms of
# the GNU General Public License version 2.
# There is NO WARRANTY, to the extent permitted by law.
#
# Written by René 'Necoro' Neumann <necoro@necoro.net>
-"""A module containing the management of the plugin system."""
-
from __future__ import absolute_import
-import os, os.path
-from xml.dom.minidom import parse
-from lxml import etree
-
-from .backend import system
-from .constants import PLUGIN_DIR, XSD_LOCATION
-from .helper import debug, info, warning, error, flatten
+import os
+import os.path as osp
+from collections import defaultdict
+from functools import wraps
-class PluginImportException (ImportError):
- pass
+from .helper import debug, warning, info, error
+from .constants import PLUGIN_DIR
+from . import plugins as plugin_module
-class UnmatchedDepsException (Exception):
+class PluginLoadException (Exception):
pass
-class Options (object):
- """The <options>-element."""
-
- __options = ("disabled", "blocking")
-
- def __init__ (self, options = None):
-
- self.disabled = False
- self.blocking = False
-
- if options:
- self.parse(options)
-
- def parse (self, options):
- for opt in options:
- 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)
-
- def set (self, name, value):
- return self.__setattr__(name, value)
-
-class Menu:
- """A single <menu>-element."""
- def __init__ (self, plugin, label, call):
- """Constructor.
-
- @param plugin: the plugin this menu belongs to
- @type plugin: Plugin
- @param label: the label to show
- @type label: string
- @param call: the function to call relative to the import statement
- @type call: string
-
- @raises PluginImportException: if the plugin's import could not be imported"""
+class Menu (object):
+ __slots__ = ("label", "call")
+ def __init__ (self, label, call):
self.label = label
- self.plugin = plugin
-
- if self.plugin.needs_import(): # get import
- imp = self.plugin.get_import()
- try:
- mod = __import__(imp, globals(), locals(), [call])
- except ImportError:
- if self.plugin.unmatched_deps:
- raise UnmatchedDepsException
- else:
- raise PluginImportException, imp
-
- try:
- self.call = eval("mod."+call) # build function
- except AttributeError:
- raise PluginImportException, imp
- else:
- try:
- self.call = eval(call)
- except AttributeError:
- raise PluginImportException, imp
-
-class Connect:
- """A single <connect>-element."""
-
- def __init__ (self, hook, type, depend_plugin):
- """Constructor.
-
- @param hook: the parent Hook
- @type hook: Hook
- @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"""
-
- self.type = type
- self.hook = hook
- self.depend_plugin = depend_plugin
-
- def is_before_type (self):
- return self.type == "before"
-
- def is_after_type (self):
- return self.type == "after"
-
- def is_override_type (self):
- return self.type == "override"
-
-class Hook:
- """A single <hook>-element."""
-
- def __init__ (self, plugin, hook, call):
- """Constructor.
+ self.call = call
- @param plugin: the parent Plugin
- @type plugin: Plugin
- @param hook: the hook to add to
- @type hook: string
- @param call: the call to make
- @type call: string"""
+class Call (object):
+ __slots__ = ("plugin", "hook", "call", "type", "dep")
+ def __init__ (self, plugin, hook, call, type = "before", dep = None):
self.plugin = plugin
self.hook = hook
self.call = call
- self.connects = []
-
- def parse_connects (self, connects):
- """This gets a list of <connect>-elements and parses them.
-
- @param connects: the list of <connect>'s
- @type connects: NodeList"""
-
- if not connects: # no connects - assume "before" connect
- self.connects.append(Connect(self, "before", None))
-
- for c in connects:
- type = c.getAttribute("type")
- if type == '':
- type = "before"
-
- # get dep_plugin if available
- dep_plugin = None
- if c.hasChildNodes():
- nodes = c.childNodes
- dep_plugin = nodes[0].nodeValue.strip()
-
- connect = Connect(self, type, dep_plugin)
- self.connects.append(connect)
-
-class Plugin:
- """A complete plugin."""
-
- (STAT_DISABLED, STAT_TEMP_ENABLED, STAT_ENABLED, STAT_TEMP_DISABLED) = range(4)
-
- def __init__ (self, file, name, author):
- """Constructor.
-
- @param file: the file name of the plugin.xml
- @type file: string
- @param name: the name of the plugin
- @type name: Node
- @param author: the author of the plugin
- @type author: Node"""
-
- self.file = file
- self.name = name.firstChild.nodeValue.strip()
- self.author = author.firstChild.nodeValue.strip()
- self.description = ""
- self._import = None
- self.hooks = []
- self.menus = []
- self.deps = []
- self.unmatched_deps = []
- self.options = Options()
-