[PATCH 06/16] Move the path definitions to Interface and pass it to the Hubs from there
Martin Sivak
msivak at redhat.com
Thu Dec 6 15:46:29 UTC 2012
---
pyanaconda/ui/__init__.py | 30 +++++++++++++++++-----
pyanaconda/ui/common.py | 14 ++++++++++
pyanaconda/ui/gui/__init__.py | 44 +++++++++++++++++++++++---------
pyanaconda/ui/gui/categories/__init__.py | 2 +-
pyanaconda/ui/gui/hubs/__init__.py | 14 ++++------
pyanaconda/ui/tui/__init__.py | 24 ++++++++++++++---
pyanaconda/ui/tui/hubs/__init__.py | 2 +-
7 files changed, 96 insertions(+), 34 deletions(-)
diff --git a/pyanaconda/ui/__init__.py b/pyanaconda/ui/__init__.py
index aabc719..26e540a 100644
--- a/pyanaconda/ui/__init__.py
+++ b/pyanaconda/ui/__init__.py
@@ -22,6 +22,7 @@
__all__ = ["UserInterface"]
import os
+import inspect
from common import collect
class UserInterface(object):
@@ -59,6 +60,27 @@ class UserInterface(object):
from pyanaconda.errors import errorHandler
errorHandler.ui = self
+ @property
+ def basepath(self):
+ """returns the directory name for UI subtree"""
+ return os.path.dirname(inspect.getfile(self.__class__))
+
+ @property
+ def basemask(self):
+ """returns the python module name for basepath directory"""
+ return "pyanaconda.ui"
+
+ @property
+ def paths(self):
+ """return dictionary mapping plugin elements (spokes, hubs, categories)
+ to a list of tuples (module mask, search path)"""
+ return {
+ "spokes": [(self.basemask + ".spokes.%s",
+ os.path.join(self.basepath, "spokes"))],
+ "hubs": [(self.basemask + ".hubs.%s",
+ os.path.join(self.basepath, "hubs"))]
+ }
+
def setup(self, data):
"""Construct all the objects required to implement this interface.
This method must be provided by all subclasses.
@@ -121,7 +143,7 @@ class UserInterface(object):
return standalones
- def _orderActionClasses(self, spokes, hubs, standalone_class):
+ def _orderActionClasses(self, spokes, hubs):
"""Order all the Hub and Spoke classes which should be enqueued for
processing according to their pre/post dependencies.
@@ -129,15 +151,9 @@ class UserInterface(object):
to the hub dependencies
:type spokes: list of Spoke instances
- :param path: the directory we are picking up modules from
- :type path: string
-
:param hubs: the list of Hub classes we check to be in pre/postForHub
attribute of Spokes to pick up
:type hubs: common.Hub based types
-
- :param standalone_class: the parent type of Spokes we want to pick up
- :type standalone_class: common.StandaloneSpoke based types
"""
actionClasses = []
diff --git a/pyanaconda/ui/common.py b/pyanaconda/ui/common.py
index d5ff8af..11f5e0b 100644
--- a/pyanaconda/ui/common.py
+++ b/pyanaconda/ui/common.py
@@ -23,6 +23,14 @@
import os
import imp
import inspect
+import copy
+
+class PathDict(dict):
+ """Dictionary class supporting + operator"""
+ def __add__(self, ext):
+ new_dict = copy.copy(self)
+ new_dict.update(ext)
+ return new_dict
class UIObject(object):
"""This is the base class from which all other UI classes are derived. It
@@ -377,7 +385,13 @@ class Hub(UIObject):
self.storage = storage
self.payload = payload
self.instclass = instclass
+ self.paths = {}
+ def set_path(self, path_id, paths):
+ """Update the paths attribute with list of tuples in the form (module
+ name format string, directory name)"""
+ self.paths[path_id] = paths
+
def collect(module_pattern, path, pred):
"""Traverse the directory (given by path), import all files as a module
module_pattern % filename and find all classes within that match
diff --git a/pyanaconda/ui/gui/__init__.py b/pyanaconda/ui/gui/__init__.py
index f9b51e2..a09ce20 100644
--- a/pyanaconda/ui/gui/__init__.py
+++ b/pyanaconda/ui/gui/__init__.py
@@ -28,6 +28,7 @@ from pyanaconda.product import distributionText, isFinal
from pyanaconda.ui import UserInterface, common
from pyanaconda.ui.gui.utils import enlightbox, gtk_thread_wait
from pyanaconda.product import isFinal, productName, productVersion
+import os.path
import gettext
_ = lambda x: gettext.ldgettext("anaconda", x)
@@ -62,17 +63,19 @@ class GraphicalUserInterface(UserInterface):
import ctypes
ctypes.CDLL("libAnacondaWidgets.so.0", ctypes.RTLD_GLOBAL)
+ @property
+ def basemask(self):
+ return "pyanaconda.ui.gui"
+
def _list_hubs(self):
- from hubs.summary import SummaryHub
- from hubs.progress import ProgressHub
+ """Return a list of Hub classes to be imported to this interface"""
+ from .hubs.summary import SummaryHub
+ from .hubs.progress import ProgressHub
return [SummaryHub, ProgressHub]
- def _list_standalone_paths(self):
- path = os.path.join(os.path.dirname(__file__), "spokes")
- return [("pyanaconda.ui.gui.spokes.%s", path)]
-
def _is_standalone(self, obj):
- from spokes import StandaloneSpoke
+ """Is the spoke passes as obj standalone?"""
+ from .spokes import StandaloneSpoke
return isinstance(obj, StandaloneSpoke)
def setup(self, data):
@@ -82,13 +85,25 @@ class GraphicalUserInterface(UserInterface):
self.data = data
def getActionClasses(self, hubs):
- from spokes import StandaloneSpoke
+ """Grab all relevant standalone spokes, add them to the passed
+ list of hubs and order the list according to the
+ relationships between hubs and standalones."""
+ from .spokes import StandaloneSpoke
# First, grab a list of all the standalone spokes.
- standalones = self._collectActionClasses(self._list_standalone_paths(), StandaloneSpoke)
+ standalones = self._collectActionClasses(self.paths["spokes"], StandaloneSpoke)
# Second, order them according to their relationship
- return self._orderActionClasses(standalones, hubs, StandaloneSpoke)
+ return self._orderActionClasses(standalones, hubs)
+
+ @property
+ def paths(self):
+ _paths = UserInterface.paths.fget(self)
+ _paths.update({"categories": [(self.basemask + ".categories.%s",
+ os.path.join(self.basepath, "categories"))]
+ })
+ return _paths
+
def _instantiateAction(self, actionClass):
from spokes import StandaloneSpoke
@@ -97,10 +112,15 @@ class GraphicalUserInterface(UserInterface):
# spoke API and setting up continue/quit signal handlers.
obj = actionClass(self.data, self.storage, self.payload, self.instclass)
+ # set spoke search paths in Hubs
+ if hasattr(obj, "set_path"):
+ obj.set_path("spokes", self.paths["spokes"])
+ obj.set_path("categories", self.paths["categories"])
+
# If we are doing a kickstart install, some standalone spokes
- # could already be filled out. In that case, we do not want
+ # could already be filled out. In taht case, we do not want
# to display them.
- if isinstance(obj, StandaloneSpoke) and obj.completed:
+ if self._is_standalone(obj) and obj.completed:
del(obj)
return None
diff --git a/pyanaconda/ui/gui/categories/__init__.py b/pyanaconda/ui/gui/categories/__init__.py
index c318901..14dc2a0 100644
--- a/pyanaconda/ui/gui/categories/__init__.py
+++ b/pyanaconda/ui/gui/categories/__init__.py
@@ -77,7 +77,7 @@ def collect_categories(mask_paths):
"""
categories = []
for mask, path in mask_paths:
- categories.extend(collect(mask, path, lambda obj: getattr(obj, "displayOnHub", None) != None)
+ categories.extend(collect(mask, path, lambda obj: getattr(obj, "displayOnHub", None) != None))
return categories
diff --git a/pyanaconda/ui/gui/hubs/__init__.py b/pyanaconda/ui/gui/hubs/__init__.py
index 4447367..f9cc933 100644
--- a/pyanaconda/ui/gui/hubs/__init__.py
+++ b/pyanaconda/ui/gui/hubs/__init__.py
@@ -22,7 +22,9 @@
import gettext
_ = lambda x: gettext.ldgettext("anaconda", x)
+
# pylint: disable-msg=E0611
+import os
from gi.repository import GLib
from pyanaconda.flags import flags
@@ -111,12 +113,6 @@ class Hub(GUIObject, common.Hub):
action.apply()
action.execute()
- def _list_spokes_mask_paths(self):
- return [("pyanaconda.ui.gui.spokes.%s", os.path.join(os.path.dirname(__file__), "spokes"))]
-
- def _list_categories_mask_paths(self):
- return [("pyanaconda.ui.gui.categories.%s", os.path.join(os.path.dirname(__file__), "categories"))]
-
def _collectCategoriesAndSpokes(self):
"""collects categories and spokes to be displayed on this Hub
@@ -128,10 +124,10 @@ class Hub(GUIObject, common.Hub):
# Collect all the categories this hub displays, then collect all the
# spokes belonging to all those categories.
- categories = sorted(filter(lambda c: c.displayOnHub == self.__class__, collect_categories(self._list_categories_mask_paths())),
+ categories = sorted(filter(lambda c: c.displayOnHub == self.__class__, collect_categories(self.paths["categories"])),
key=lambda c: c.title)
for c in categories:
- ret[c] = collect_spokes(self._list_spokes_mask_paths(), c.__name__)
+ ret[c] = collect_spokes(self.paths["spokes"], c.__name__)
return ret
@@ -250,7 +246,7 @@ class Hub(GUIObject, common.Hub):
@property
def continuePossible(self):
- return len(self._incompleteSpokes) == 0 and len(self._notReadySpokes) == 0
+ return len(self._incompleteSpokes)==0 and len(self._notReadySpokes) == 0
def _updateContinueButton(self):
self.continueButton.set_sensitive(self.continuePossible)
diff --git a/pyanaconda/ui/tui/__init__.py b/pyanaconda/ui/tui/__init__.py
index c4a15a0..cccbf70 100644
--- a/pyanaconda/ui/tui/__init__.py
+++ b/pyanaconda/ui/tui/__init__.py
@@ -129,27 +129,43 @@ class TextUserInterface(ui.UserInterface):
ui.UserInterface.__init__(self, storage, payload, instclass)
self._app = None
+ @property
+ def basemask(self):
+ return "pyanaconda.ui.tui"
+
+ def _list_hubs(self):
+ """returns the list of hubs to use"""
+ return [SummaryHub, ProgressHub]
+
+ def _is_standalone(self, spoke):
+ """checks if the passed spoke is standalone"""
+ return isinstance(spoke, StandaloneSpoke)
+
def setup(self, data):
"""Construct all the objects required to implement this interface.
This method must be provided by all subclasses.
"""
self._app = tui.App(u"Anaconda", yes_or_no_question = YesNoDialog)
- self._hubs = [SummaryHub, ProgressHub]
+ _hubs = self._list_hubs()
# First, grab a list of all the standalone spokes.
path = os.path.join(os.path.dirname(__file__), "spokes")
- actionClasses = self.getActionClasses("pyanaconda.ui.tui.spokes.%s", path, self._hubs, StandaloneSpoke)
-
+ spokes = self._collectActionClasses(self.paths["spokes"], StandaloneSpoke)
+ actionClasses = self._orderActionClasses(spokes, _hubs)
+
for klass in actionClasses:
obj = klass(self._app, data, self.storage, self.payload, self.instclass)
# If we are doing a kickstart install, some standalone spokes
# could already be filled out. In taht case, we do not want
# to display them.
- if isinstance(obj, StandaloneSpoke) and obj.completed:
+ if self._is_standalone(obj) and obj.completed:
del(obj)
continue
+ if hasattr(obj, "set_path"):
+ obj.set_path("spokes", self.paths["spokes"])
+
self._app.schedule_screen(obj)
def run(self):
diff --git a/pyanaconda/ui/tui/hubs/__init__.py b/pyanaconda/ui/tui/hubs/__init__.py
index 0f505f7..d669bc7 100644
--- a/pyanaconda/ui/tui/hubs/__init__.py
+++ b/pyanaconda/ui/tui/hubs/__init__.py
@@ -52,7 +52,7 @@ class TUIHub(TUIObject, common.Hub):
# look for spokes having category present in self.categories
for c in self.categories:
- spokes = collect_spokes([("pyanaconda.ui.tui.spokes.%s", os.path.join(os.path.dirname(__file__), "spokes"))], c)
+ spokes = collect_spokes(self.paths["spokes"], c)
# sort them according to their priority
for s in sorted(spokes, key = lambda s: s.priority):
--
1.7.11.7
More information about the anaconda-patches
mailing list