[PATCH 06/16] Move the path definitions to Interface and pass it to the Hubs from there
Vratislav Podzimek
vpodzime at redhat.com
Thu Dec 13 15:18:45 UTC 2012
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_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?"""
^^ 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 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
^^^^ typo
> # 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
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)
> 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):
--
Vratislav Podzimek
Anaconda Rider | Red Hat, Inc. | Brno - Czech Republic
More information about the anaconda-patches
mailing list