diff options
Diffstat (limited to 'waflib/extras/review.py')
m--------- | waflib | 0 | ||||
-rw-r--r-- | waflib/extras/review.py | 325 |
2 files changed, 0 insertions, 325 deletions
diff --git a/waflib b/waflib new file mode 160000 +Subproject 2314e236ca6e7d94a26c3c17091da0f25f5867f diff --git a/waflib/extras/review.py b/waflib/extras/review.py deleted file mode 100644 index 561e0621..00000000 --- a/waflib/extras/review.py +++ /dev/null @@ -1,325 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 -# Laurent Birtz, 2011 -# moved the code into a separate tool (ita) - -""" -There are several things here: -- a different command-line option management making options persistent -- the review command to display the options set - -Assumptions: -- configuration options are not always added to the right group (and do not count on the users to do it...) -- the options are persistent between the executions (waf options are NOT persistent by design), even for the configuration -- when the options change, the build is invalidated (forcing a reconfiguration) -""" - -import os, textwrap, shutil -from waflib import Logs, Context, ConfigSet, Options, Build, Configure - -class Odict(dict): - """Ordered dictionary""" - def __init__(self, data=None): - self._keys = [] - dict.__init__(self) - if data: - # we were provided a regular dict - if isinstance(data, dict): - self.append_from_dict(data) - - # we were provided a tuple list - elif type(data) == list: - self.append_from_plist(data) - - # we were provided invalid input - else: - raise Exception("expected a dict or a tuple list") - - def append_from_dict(self, dict): - map(self.__setitem__, dict.keys(), dict.values()) - - def append_from_plist(self, plist): - for pair in plist: - if len(pair) != 2: - raise Exception("invalid pairs list") - for (k, v) in plist: - self.__setitem__(k, v) - - def __delitem__(self, key): - if not key in self._keys: - raise KeyError(key) - dict.__delitem__(self, key) - self._keys.remove(key) - - def __setitem__(self, key, item): - dict.__setitem__(self, key, item) - if key not in self._keys: - self._keys.append(key) - - def clear(self): - dict.clear(self) - self._keys = [] - - def copy(self): - return Odict(self.plist()) - - def items(self): - return zip(self._keys, self.values()) - - def keys(self): - return list(self._keys) # return a copy of the list - - def values(self): - return map(self.get, self._keys) - - def plist(self): - p = [] - for k, v in self.items(): - p.append( (k, v) ) - return p - - def __str__(self): - buf = [] - buf.append("{ ") - for k, v in self.items(): - buf.append('%r : %r, ' % (k, v)) - buf.append("}") - return ''.join(buf) - -review_options = Odict() -""" -Ordered dictionary mapping configuration option names to their optparse option. -""" - -review_defaults = {} -""" -Dictionary mapping configuration option names to their default value. -""" - -old_review_set = None -""" -Review set containing the configuration values before parsing the command line. -""" - -new_review_set = None -""" -Review set containing the configuration values after parsing the command line. -""" - -class OptionsReview(Options.OptionsContext): - def __init__(self, **kw): - super(self.__class__, self).__init__(**kw) - - def prepare_config_review(self): - """ - Find the configuration options that are reviewable, detach - their default value from their optparse object and store them - into the review dictionaries. - """ - gr = self.get_option_group('configure options') - for opt in gr.option_list: - if opt.action != 'store' or opt.dest in ("out", "top"): - continue - review_options[opt.dest] = opt - review_defaults[opt.dest] = opt.default - if gr.defaults.has_key(opt.dest): - del gr.defaults[opt.dest] - opt.default = None - - def parse_args(self): - self.prepare_config_review() - self.parser.get_option('--prefix').help = 'installation prefix' - super(OptionsReview, self).parse_args() - Context.create_context('review').refresh_review_set() - -class ReviewContext(Context.Context): - '''reviews the configuration values''' - - cmd = 'review' - - def __init__(self, **kw): - super(self.__class__, self).__init__(**kw) - - out = Options.options.out - if not out: - out = getattr(Context.g_module, Context.OUT, None) - if not out: - out = Options.lockfile.replace('.lock-waf', '') - self.build_path = (os.path.isabs(out) and self.root or self.path).make_node(out).abspath() - """Path to the build directory""" - - self.cache_path = os.path.join(self.build_path, Build.CACHE_DIR) - """Path to the cache directory""" - - self.review_path = os.path.join(self.cache_path, 'review.cache') - """Path to the review cache file""" - - def execute(self): - """ - Display and store the review set. Invalidate the cache as required. - """ - if not self.compare_review_set(old_review_set, new_review_set): - self.invalidate_cache() - self.store_review_set(new_review_set) - print(self.display_review_set(new_review_set)) - - def invalidate_cache(self): - """Invalidate the cache to prevent bad builds.""" - try: - Logs.warn("Removing the cached configuration since the options have changed") - shutil.rmtree(self.cache_path) - except: - pass - - def refresh_review_set(self): - """ - Obtain the old review set and the new review set, and import the new set. - """ - global old_review_set, new_review_set - old_review_set = self.load_review_set() - new_review_set = self.update_review_set(old_review_set) - self.import_review_set(new_review_set) - - def load_review_set(self): - """ - Load and return the review set from the cache if it exists. - Otherwise, return an empty set. - """ - if os.path.isfile(self.review_path): - return ConfigSet.ConfigSet(self.review_path) - return ConfigSet.ConfigSet() - - def store_review_set(self, review_set): - """ - Store the review set specified in the cache. - """ - if not os.path.isdir(self.cache_path): - os.makedirs(self.cache_path) - review_set.store(self.review_path) - - def update_review_set(self, old_set): - """ - Merge the options passed on the command line with those imported - from the previous review set and return the corresponding - preview set. - """ - - # Convert value to string. It's important that 'None' maps to - # the empty string. - def val_to_str(val): - if val == None or val == '': - return '' - return str(val) - - new_set = ConfigSet.ConfigSet() - opt_dict = Options.options.__dict__ - - for name in review_options.keys(): - # the option is specified explicitly on the command line - if name in opt_dict: - # if the option is the default, pretend it was never specified - if val_to_str(opt_dict[name]) != val_to_str(review_defaults[name]): - new_set[name] = opt_dict[name] - # the option was explicitly specified in a previous command - elif name in old_set: - new_set[name] = old_set[name] - - return new_set - - def import_review_set(self, review_set): - """ - Import the actual value of the reviewable options in the option - dictionary, given the current review set. - """ - for name in review_options.keys(): - if name in review_set: - value = review_set[name] - else: - value = review_defaults[name] - setattr(Options.options, name, value) - - def compare_review_set(self, set1, set2): - """ - Return true if the review sets specified are equal. - """ - if len(set1.keys()) != len(set2.keys()): - return False - for key in set1.keys(): - if not key in set2 or set1[key] != set2[key]: - return False - return True - - def display_review_set(self, review_set): - """ - Return the string representing the review set specified. - """ - term_width = Logs.get_term_cols() - lines = [] - for dest in review_options.keys(): - opt = review_options[dest] - name = ", ".join(opt._short_opts + opt._long_opts) - help = opt.help - actual = None - if dest in review_set: - actual = review_set[dest] - default = review_defaults[dest] - lines.append(self.format_option(name, help, actual, default, term_width)) - return "Configuration:\n\n" + "\n\n".join(lines) + "\n" - - def format_option(self, name, help, actual, default, term_width): - """ - Return the string representing the option specified. - """ - def val_to_str(val): - if val == None or val == '': - return "(void)" - return str(val) - - max_name_len = 20 - sep_len = 2 - - w = textwrap.TextWrapper() - w.width = term_width - 1 - if w.width < 60: - w.width = 60 - - out = "" - - # format the help - out += w.fill(help) + "\n" - - # format the name - name_len = len(name) - out += Logs.colors.CYAN + name + Logs.colors.NORMAL - - # set the indentation used when the value wraps to the next line - w.subsequent_indent = " ".rjust(max_name_len + sep_len) - w.width -= (max_name_len + sep_len) - - # the name string is too long, switch to the next line - if name_len > max_name_len: - out += "\n" + w.subsequent_indent - - # fill the remaining of the line with spaces - else: - out += " ".rjust(max_name_len + sep_len - name_len) - - # format the actual value, if there is one - if actual != None: - out += Logs.colors.BOLD + w.fill(val_to_str(actual)) + Logs.colors.NORMAL + "\n" + w.subsequent_indent - - # format the default value - default_fmt = val_to_str(default) - if actual != None: - default_fmt = "default: " + default_fmt - out += Logs.colors.NORMAL + w.fill(default_fmt) + Logs.colors.NORMAL - - return out - -# Monkey-patch ConfigurationContext.execute() to have it store the review set. -old_configure_execute = Configure.ConfigurationContext.execute -def new_configure_execute(self): - old_configure_execute(self) - Context.create_context('review').store_review_set(new_review_set) -Configure.ConfigurationContext.execute = new_configure_execute - |