diff options
author | Paul Eggleton <paul.eggleton@linux.intel.com> | 2015-08-24 15:00:22 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-08-24 23:47:07 +0100 |
commit | bb34181b42b62e0476ba9e12f9125ed9f785cf23 (patch) | |
tree | b149c41e4509e67f4a0601b8a9bf944093b89958 | |
parent | d893a2503da29ec99b3a911f8877cc59e7e6b50d (diff) | |
download | poky-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-x | bitbake/lib/bb/main.py | 60 |
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") | |||
41 | class BBMainException(Exception): | 41 | class BBMainException(Exception): |
42 | pass | 42 | pass |
43 | 43 | ||
44 | def present_options(optionlist): | ||
45 | if len(optionlist) > 1: | ||
46 | return ' or '.join([', '.join(optionlist[:-1]), optionlist[-1]]) | ||
47 | else: | ||
48 | return optionlist[0] | ||
49 | |||
50 | class 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 | |||
44 | def list_extension_modules(pkg, checkattr): | 66 | def 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 | ||
73 | def import_extension_module(pkg, modulename): | 98 | def 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": |