On Thu, 2012-12-06 at 16:46 +0100, Martin Sivak wrote:
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_dictclass 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 (modulename format string, directory name)"""self.paths[path_id] = pathsdef 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 SummaryHubfrom hubs.progress import ProgressHub
"""Return a list of Hub classes to be imported to this interface"""from .hubs.summary import SummaryHubfrom .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?"""
^^ typo?
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 passedlist of hubs and order the list according to therelationships 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 _pathsdef _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 Hubsif 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
^^^^ typo
# to display them.
if isinstance(obj, StandaloneSpoke) and obj.completed:
if self._is_standalone(obj) and obj.completed: del(obj) return Nonediff --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
No newline needed and # pylint:... should stay next to the GLib import.
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
^^ missing whitespace
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) continueif 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):