Clone of official tools
Diff: config.py
- Revision:
- 24:25bff2709c20
- Parent:
- 13:ab47a20b66f0
- Child:
- 29:1210849dba19
--- a/config.py Sat Jul 16 22:51:17 2016 +0100 +++ b/config.py Mon Aug 01 09:10:17 2016 +0100 @@ -137,6 +137,42 @@ self.macro_name = name self.macro_value = None +# Representation of overrides for cumulative attributes +class ConfigCumulativeOverride: + def __init__(self, name, additions=set(), removals=set(), strict=False): + self.name = name + self.additions = set(additions) + self.removals = set(removals) + self.strict = strict + + # Add attr to the cumulative override + def remove_cumulative_overrides(self, overrides): + for override in overrides: + if override in self.additions: + raise ConfigException("Configuration conflict. The %s %s both added and removed." % (self.name[:-1], override)) + + self.removals |= set(overrides) + + # Remove attr from the cumulative overrides + def add_cumulative_overrides(self, overrides): + for override in overrides: + if (override in self.removals or (self.strict and override not in self.additions)): + raise ConfigException("Configuration conflict. The %s %s both added and removed." % (self.name[:-1], override)) + + self.additions |= set(overrides) + + # Enable strict set of cumulative overrides for the specified attr + def strict_cumulative_overrides(self, overrides): + self.remove_cumulative_overrides(self.additions - set(overrides)) + self.add_cumulative_overrides(overrides) + self.strict = True + + def update_target(self, target): + setattr(target, self.name, list( + (set(getattr(target, self.name, [])) | self.additions) - self.removals)) + + + # 'Config' implements the mbed configuration mechanism class Config: # Libraries and applications have different names for their configuration files @@ -152,7 +188,7 @@ # Allowed features in configurations __allowed_features = [ - "UVISOR", "BLE", "CLIENT", "IPV4", "IPV6" + "UVISOR", "BLE", "CLIENT", "IPV4", "IPV6", "COMMON_PAL", "STORAGE" ] # The initialization arguments for Config are: @@ -184,9 +220,12 @@ self.processed_configs = {} self.target = target if isinstance(target, basestring) else target.name self.target_labels = Target.get_target(self.target).get_labels() - self.added_features = set() - self.removed_features = set() - self.removed_unecessary_features = False + + self.cumulative_overrides = { key: ConfigCumulativeOverride(key) + for key in Target._Target__cumulative_attributes } + + self._process_config_and_overrides(self.app_config_data, {}, "app", "application") + self.target_labels = Target.get_target(self.target).get_labels() # Add one or more configuration files def add_config_files(self, flist): @@ -222,23 +261,6 @@ params[full_name] = ConfigParameter(name, v if isinstance(v, dict) else {"value": v}, unit_name, unit_kind) return params - # Add features to the available features - def remove_features(self, features): - for feature in features: - if feature in self.added_features: - raise ConfigException("Configuration conflict. Feature %s both added and removed." % feature) - - self.removed_features |= set(features) - - # Remove features from the available features - def add_features(self, features): - for feature in features: - if (feature in self.removed_features - or (self.removed_unecessary_features and feature not in self.added_features)): - raise ConfigException("Configuration conflict. Feature %s both added and removed." % feature) - - self.added_features |= set(features) - # Helper function: process "config_parameters" and "target_config_overrides" in a given dictionary # data: the configuration data of the library/appliation # params: storage for the discovered configuration parameters @@ -250,21 +272,25 @@ for label, overrides in data.get("target_overrides", {}).items(): # If the label is defined by the target or it has the special value "*", process the overrides if (label == '*') or (label in self.target_labels): - # Parse out features - if 'target.features' in overrides: - features = overrides['target.features'] - self.remove_features(self.added_features - set(features)) - self.add_features(features) - self.removed_unecessary_features = True - del overrides['target.features'] + # Check for invalid cumulative overrides in libraries + if (unit_kind == 'library' and + any(attr.startswith('target.extra_labels') for attr in overrides.iterkeys())): + raise ConfigException("Target override '%s' in '%s' is only allowed at the application level" + % ("target.extra_labels", ConfigParameter.get_display_name(unit_name, unit_kind, label))) - if 'target.features_add' in overrides: - self.add_features(overrides['target.features_add']) - del overrides['target.features_add'] + # Parse out cumulative overrides + for attr, cumulatives in self.cumulative_overrides.iteritems(): + if 'target.'+attr in overrides: + cumulatives.strict_cumulative_overrides(overrides['target.'+attr]) + del overrides['target.'+attr] - if 'target.features_remove' in overrides: - self.remove_features(overrides['target.features_remove']) - del overrides['target.features_remove'] + if 'target.'+attr+'_add' in overrides: + cumulatives.add_cumulative_overrides(overrides['target.'+attr+'_add']) + del overrides['target.'+attr+'_add'] + + if 'target.'+attr+'_remove' in overrides: + cumulatives.remove_cumulative_overrides(overrides['target.'+attr+'_remove']) + del overrides['target.'+attr+'_remove'] # Consider the others as overrides for name, v in overrides.items(): @@ -275,6 +301,10 @@ else: self.config_errors.append(ConfigException("Attempt to override undefined parameter '%s' in '%s'" % (full_name, ConfigParameter.get_display_name(unit_name, unit_kind, label)))) + + for cumulatives in self.cumulative_overrides.itervalues(): + cumulatives.update_target(Target.get_target(self.target)) + return params # Read and interpret configuration data defined by targets @@ -389,8 +419,8 @@ def get_features(self): params, _ = self.get_config_data() self._check_required_parameters(params) - features = ((set(Target.get_target(self.target).features) - | self.added_features) - self.removed_features) + self.cumulative_overrides['features'].update_target(Target.get_target(self.target)) + features = Target.get_target(self.target).features for feature in features: if feature not in self.__allowed_features: