[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