All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paul Eggleton <paul.eggleton@linux.intel.com>
To: bitbake-devel@lists.openembedded.org
Subject: [PATCH v2] lib/bb/main: consolidate UI/server extension listing and loading
Date: Tue, 18 Aug 2015 11:29:46 +0100	[thread overview]
Message-ID: <1439893786-28572-1-git-send-email-paul.eggleton@linux.intel.com> (raw)
In-Reply-To: <CAJTo0LagN2RZRA0G1LW=nQMTRBidy0T87q5HMY_2BYZkd3nPVw@mail.gmail.com>

Provide us with a means of showing the list of UIs / server choices for
the command line help, and do the processing in one place for both.

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
---

Changes since v1:
 - Handle SystemExit when trying to import the ui module i.e.
   don't blow up when we try to import the hob module and PyGTK+
   isn't installed
 - Format the options a little bit more nicely in the help text

(also pushed to the paule/tinfoil2-pre branch)


 lib/bb/main.py | 85 +++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 54 insertions(+), 31 deletions(-)

diff --git a/lib/bb/main.py b/lib/bb/main.py
index 4d77408..c98cf44 100755
--- a/lib/bb/main.py
+++ b/lib/bb/main.py
@@ -41,22 +41,44 @@ logger = logging.getLogger("BitBake")
 class BBMainException(Exception):
     pass
 
-def get_ui(config):
-    if not config.ui:
-        # modify 'ui' attribute because it is also read by cooker
-        config.ui = os.environ.get('BITBAKE_UI', 'knotty')
-
-    interface = config.ui
-
+def list_extension_modules(pkg, checkattr):
+    """
+    Lists extension modules in a specific Python package
+    (e.g. UIs, servers)
+    Parameters:
+        pkg: previously imported Python package to list
+        checkattr: attribute to look for in module to determine if it's valid
+            as the type of extension you are looking for
+    """
+    import pkgutil
+    pkgdir = os.path.dirname(pkg.__file__)
+
+    modules = []
+    for _, modulename, _ in pkgutil.iter_modules([pkgdir]):
+        if os.path.isdir(os.path.join(pkgdir, modulename)):
+            # ignore directories
+            continue
+        try:
+            module = __import__(pkg.__name__, fromlist=[modulename])
+        except (ImportError, SystemExit):
+            # If we can't import it, it's not valid
+            continue
+        module_if = getattr(module, modulename)
+        if getattr(module_if, 'hidden_extension', False):
+            continue
+        if not checkattr or hasattr(module_if, checkattr):
+            modules.append(modulename)
+    return modules
+
+def import_extension_module(pkg, modulename):
     try:
         # Dynamically load the UI based on the ui name. Although we
         # suggest a fixed set this allows you to have flexibility in which
         # ones are available.
-        module = __import__("bb.ui", fromlist = [interface])
-        return getattr(module, interface)
+        module = __import__(pkg.__name__, fromlist = [modulename])
+        return getattr(module, modulename)
     except AttributeError:
-        raise BBMainException("FATAL: Invalid user interface '%s' specified.\n"
-                 "Valid interfaces: depexp, goggle, ncurses, hob, knotty [default]." % interface)
+        raise BBMainException("FATAL: Unable to import extension module %s from %s" % (modulename, pkg.__name__))
 
 
 # Display bitbake/OE warnings via the BitBake.Warnings logger, ignoring others"""
@@ -146,11 +168,25 @@ class BitBakeConfigParameters(cookerdata.ConfigParameters):
         parser.add_option("-P", "--profile", help = "Profile the command and save reports.",
                    action = "store_true", dest = "profile", default = False)
 
-        parser.add_option("-u", "--ui", help = "The user interface to use (e.g. knotty, hob, depexp).",
-                   action = "store", dest = "ui")
-
-        parser.add_option("-t", "--servertype", help = "Choose which server to use, process or xmlrpc.",
-                   action = "store", dest = "servertype")
+        def present_options(optionlist):
+            if len(optionlist) > 1:
+                return ' or '.join([', '.join(optionlist[:-1]), optionlist[-1]])
+            else:
+                return optionlist[0]
+
+        env_ui = os.environ.get('BITBAKE_UI', None)
+        valid_uis = list_extension_modules(bb.ui, 'main')
+        default_ui = env_ui or 'knotty'
+        if env_ui and not env_ui in valid_uis:
+            raise BBMainException('Invalid UI "%s" specified in BITBAKE_UI environment variable - valid choices: %s' % (env_ui, present_options(valid_uis)))
+        elif not default_ui in valid_uis:
+            raise BBMainException('Default UI "%s" could not be found')
+        parser.add_option("-u", "--ui", help = "The user interface to use (%s - default %%default)." % present_options(valid_uis),
+                   action="store", dest="ui", type="choice", choices=valid_uis, default=default_ui)
+
+        valid_server_types = list_extension_modules(bb.server, 'BitBakeServer')
+        parser.add_option("-t", "--servertype", help = "Choose which server type to use (%s - default %%default)." % present_options(valid_server_types),
+                   action = "store", dest = "servertype", default = "process")
 
         parser.add_option("", "--token", help = "Specify the connection token to be used when connecting to a remote server.",
                    action = "store", dest = "xmlrpctoken")
@@ -279,21 +315,8 @@ def bitbake_main(configParams, configuration):
 
     configuration.setConfigParameters(configParams)
 
-    ui_module = get_ui(configParams)
-
-    # Server type can be xmlrpc or process currently, if nothing is specified,
-    # the default server is process
-    if configParams.servertype:
-        server_type = configParams.servertype
-    else:
-        server_type = 'process'
-
-    try:
-        module = __import__("bb.server", fromlist = [server_type])
-        servermodule = getattr(module, server_type)
-    except AttributeError:
-        raise BBMainException("FATAL: Invalid server type '%s' specified.\n"
-                              "Valid interfaces: xmlrpc, process [default]." % server_type)
+    ui_module = import_extension_module(bb.ui, configParams.ui)
+    servermodule = import_extension_module(bb.server, configParams.servertype)
 
     if configParams.server_only:
         if configParams.servertype != "xmlrpc":
-- 
2.1.0



  reply	other threads:[~2015-08-18 10:29 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-08-17 11:12 [PATCH 00/13] Fixes and refactoring Paul Eggleton
2015-08-17 11:12 ` [PATCH 01/13] Fix default function parameter assignment to a list Paul Eggleton
2015-08-17 11:12 ` [PATCH 02/13] command: intercept SystemExit to avoid trashing the server Paul Eggleton
2015-08-17 11:12 ` [PATCH 03/13] cooker: further limit inotify watches Paul Eggleton
2015-08-17 11:12 ` [PATCH 04/13] command: ensure sync commands that read configuration see updates Paul Eggleton
2015-08-17 11:12 ` [PATCH 05/13] cooker: ensure prefile/postfile can work in memory resident mode Paul Eggleton
2015-08-17 11:12 ` [PATCH 06/13] Fix -m handling if cannot connect to server Paul Eggleton
2015-08-17 11:12 ` [PATCH 07/13] lib/bb/main: consolidate UI/server extension listing and loading Paul Eggleton
2015-08-18  9:32   ` Burton, Ross
2015-08-18 10:29     ` Paul Eggleton [this message]
2015-08-17 11:12 ` [PATCH 08/13] cooker: drop appliedappendlist Paul Eggleton
2015-08-17 11:12 ` [PATCH 09/13] cooker: drop appendlist Paul Eggleton
2015-08-17 11:12 ` [PATCH 10/13] bitbake-layers: Convert flatten to use collections.bbappends Paul Eggleton
2015-08-17 11:12 ` [PATCH 11/13] bitbake-layers: refactor show-appends to stop using cooker bbappends list Paul Eggleton
2015-08-17 11:12 ` [PATCH 12/13] bitbake-layers: use "with open" consistently Paul Eggleton
2015-08-17 11:12 ` [PATCH 13/13] lib/bb/parse: properly handle OSError when updating mtime cache Paul Eggleton
2015-08-17 17:14 ` [PATCH 00/13] Fixes and refactoring Christopher Larson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1439893786-28572-1-git-send-email-paul.eggleton@linux.intel.com \
    --to=paul.eggleton@linux.intel.com \
    --cc=bitbake-devel@lists.openembedded.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.