summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2015-08-24 15:00:22 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2015-08-24 23:47:07 +0100
commitbb34181b42b62e0476ba9e12f9125ed9f785cf23 (patch)
treeb149c41e4509e67f4a0601b8a9bf944093b89958
parentd893a2503da29ec99b3a911f8877cc59e7e6b50d (diff)
downloadpoky-bb34181b42b62e0476ba9e12f9125ed9f785cf23.tar.gz
bitbake: lib/bb/main: avoid importing all server/UI modules on every execution
We're importing the server and UI modules in order to check they are valid, but it turns out that that has some nasty side-effects. We don't actually need to do this except when --help is passed or the module doesn't exist, so rearrange the code so that we only do the module listing in those two cases. Additionally, let's just go ahead and catch all errors on import; we really don't care to have them cause a failure now. (Bitbake rev: c9dc6d9c86e8b887821a6d00346bd0b09e1da97c) Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rwxr-xr-xbitbake/lib/bb/main.py60
1 files changed, 38 insertions, 22 deletions
diff --git a/bitbake/lib/bb/main.py b/bitbake/lib/bb/main.py
index 910cd64444..8762f7220a 100755
--- a/bitbake/lib/bb/main.py
+++ b/bitbake/lib/bb/main.py
@@ -41,10 +41,35 @@ logger = logging.getLogger("BitBake")
41class BBMainException(Exception): 41class BBMainException(Exception):
42 pass 42 pass
43 43
44def present_options(optionlist):
45 if len(optionlist) > 1:
46 return ' or '.join([', '.join(optionlist[:-1]), optionlist[-1]])
47 else:
48 return optionlist[0]
49
50class BitbakeHelpFormatter(optparse.IndentedHelpFormatter):
51 def format_option(self, option):
52 # We need to do this here rather than in the text we supply to
53 # add_option() because we don't want to call list_extension_modules()
54 # on every execution (since it imports all of the modules)
55 # Note also that we modify option.help rather than the returned text
56 # - this is so that we don't have to re-format the text ourselves
57 if option.dest == 'ui':
58 valid_uis = list_extension_modules(bb.ui, 'main')
59 option.help = option.help.replace('@CHOICES@', present_options(valid_uis))
60 elif option.dest == 'servertype':
61 valid_server_types = list_extension_modules(bb.server, 'BitBakeServer')
62 option.help = option.help.replace('@CHOICES@', present_options(valid_server_types))
63
64 return optparse.IndentedHelpFormatter.format_option(self, option)
65
44def list_extension_modules(pkg, checkattr): 66def list_extension_modules(pkg, checkattr):
45 """ 67 """
46 Lists extension modules in a specific Python package 68 Lists extension modules in a specific Python package
47 (e.g. UIs, servers) 69 (e.g. UIs, servers). NOTE: Calling this function will import all of the
70 submodules of the specified module in order to check for the specified
71 attribute; this can have unusual side-effects. As a result, this should
72 only be called when displaying help text or error messages.
48 Parameters: 73 Parameters:
49 pkg: previously imported Python package to list 74 pkg: previously imported Python package to list
50 checkattr: attribute to look for in module to determine if it's valid 75 checkattr: attribute to look for in module to determine if it's valid
@@ -60,7 +85,7 @@ def list_extension_modules(pkg, checkattr):
60 continue 85 continue
61 try: 86 try:
62 module = __import__(pkg.__name__, fromlist=[modulename]) 87 module = __import__(pkg.__name__, fromlist=[modulename])
63 except (ImportError, SystemExit, RuntimeError): 88 except:
64 # If we can't import it, it's not valid 89 # If we can't import it, it's not valid
65 continue 90 continue
66 module_if = getattr(module, modulename) 91 module_if = getattr(module, modulename)
@@ -70,7 +95,7 @@ def list_extension_modules(pkg, checkattr):
70 modules.append(modulename) 95 modules.append(modulename)
71 return modules 96 return modules
72 97
73def import_extension_module(pkg, modulename): 98def import_extension_module(pkg, modulename, checkattr):
74 try: 99 try:
75 # Dynamically load the UI based on the ui name. Although we 100 # Dynamically load the UI based on the ui name. Although we
76 # suggest a fixed set this allows you to have flexibility in which 101 # suggest a fixed set this allows you to have flexibility in which
@@ -78,7 +103,7 @@ def import_extension_module(pkg, modulename):
78 module = __import__(pkg.__name__, fromlist = [modulename]) 103 module = __import__(pkg.__name__, fromlist = [modulename])
79 return getattr(module, modulename) 104 return getattr(module, modulename)
80 except AttributeError: 105 except AttributeError:
81 raise BBMainException("FATAL: Unable to import extension module %s from %s" % (modulename, pkg.__name__)) 106 raise BBMainException('FATAL: Unable to import extension module "%s" from %s. Valid extension modules: %s' % (modulename, pkg.__name__, present_options(list_extension_modules(pkg, checkattr))))
82 107
83 108
84# Display bitbake/OE warnings via the BitBake.Warnings logger, ignoring others""" 109# Display bitbake/OE warnings via the BitBake.Warnings logger, ignoring others"""
@@ -104,6 +129,7 @@ class BitBakeConfigParameters(cookerdata.ConfigParameters):
104 129
105 def parseCommandLine(self, argv=sys.argv): 130 def parseCommandLine(self, argv=sys.argv):
106 parser = optparse.OptionParser( 131 parser = optparse.OptionParser(
132 formatter = BitbakeHelpFormatter(),
107 version = "BitBake Build Tool Core version %s" % bb.__version__, 133 version = "BitBake Build Tool Core version %s" % bb.__version__,
108 usage = """%prog [options] [recipename/target recipe:do_task ...] 134 usage = """%prog [options] [recipename/target recipe:do_task ...]
109 135
@@ -168,24 +194,14 @@ class BitBakeConfigParameters(cookerdata.ConfigParameters):
168 parser.add_option("-P", "--profile", help = "Profile the command and save reports.", 194 parser.add_option("-P", "--profile", help = "Profile the command and save reports.",
169 action = "store_true", dest = "profile", default = False) 195 action = "store_true", dest = "profile", default = False)
170 196
171 def present_options(optionlist):
172 if len(optionlist) > 1:
173 return ' or '.join([', '.join(optionlist[:-1]), optionlist[-1]])
174 else:
175 return optionlist[0]
176
177 env_ui = os.environ.get('BITBAKE_UI', None) 197 env_ui = os.environ.get('BITBAKE_UI', None)
178 valid_uis = list_extension_modules(bb.ui, 'main')
179 default_ui = env_ui or 'knotty' 198 default_ui = env_ui or 'knotty'
180 if env_ui and not env_ui in valid_uis: 199 # @CHOICES@ is substituted out by BitbakeHelpFormatter above
181 raise BBMainException('Invalid UI "%s" specified in BITBAKE_UI environment variable - valid choices: %s' % (env_ui, present_options(valid_uis))) 200 parser.add_option("-u", "--ui", help = "The user interface to use (@CHOICES@ - default %default).",
182 elif not default_ui in valid_uis: 201 action="store", dest="ui", default=default_ui)
183 raise BBMainException('Default UI "%s" could not be found') 202
184 parser.add_option("-u", "--ui", help = "The user interface to use (%s - default %%default)." % present_options(valid_uis), 203 # @CHOICES@ is substituted out by BitbakeHelpFormatter above
185 action="store", dest="ui", type="choice", choices=valid_uis, default=default_ui) 204 parser.add_option("-t", "--servertype", help = "Choose which server type to use (@CHOICES@ - default %default).",
186
187 valid_server_types = list_extension_modules(bb.server, 'BitBakeServer')
188 parser.add_option("-t", "--servertype", help = "Choose which server type to use (%s - default %%default)." % present_options(valid_server_types),
189 action = "store", dest = "servertype", default = "process") 205 action = "store", dest = "servertype", default = "process")
190 206
191 parser.add_option("", "--token", help = "Specify the connection token to be used when connecting to a remote server.", 207 parser.add_option("", "--token", help = "Specify the connection token to be used when connecting to a remote server.",
@@ -315,8 +331,8 @@ def bitbake_main(configParams, configuration):
315 331
316 configuration.setConfigParameters(configParams) 332 configuration.setConfigParameters(configParams)
317 333
318 ui_module = import_extension_module(bb.ui, configParams.ui) 334 ui_module = import_extension_module(bb.ui, configParams.ui, 'main')
319 servermodule = import_extension_module(bb.server, configParams.servertype) 335 servermodule = import_extension_module(bb.server, configParams.servertype, 'BitBakeServer')
320 336
321 if configParams.server_only: 337 if configParams.server_only:
322 if configParams.servertype != "xmlrpc": 338 if configParams.servertype != "xmlrpc":