Openembedded Bitbake Development
 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox