"""Utils for parsing features.""" import yaml from features import filters from features.models import feature as feature_model from features.models import feature_variant as feature_variant_model from features.models import feature_variant_force_rule as force_rule_model def parse_features_from_yaml_file(path): """Parse the features out of a yaml file. Args: path (str): path of the file to parse. Return: dict: the dictionary of all the features. """ with open(path, 'r') as stream: data = _parse_features_from_yaml(stream) return data def _parse_features_from_yaml(source): """Create features from a YAML file. Args: source (str): yaml content (it should be a string, but it can also be a stream.) Raises: Exception: if a feature name is used twice, an exception is raised. All feature names should be unique. Return: dict: the dictionary of all the features. """ feature_content = yaml.safe_load(source) if not feature_content: raise Exception('Yaml content is not valid.') features = {} for feature in feature_content: # check the feature is not already present, otherwise it means we # are most likely going to override a feature with another one (and # this shouldn't happen). feature_name = feature.get('name') if features.get(feature_name): raise Exception('This feature {} is already used.'.format(feature_name)) features.update({feature_name: _create_feature_from_dictionary(feature)}) return features def _create_feature_from_dictionary(data): """Create a feature from a dictionary. Args: data (dict): the description of a feature. It should contain variants, overrides, and the name. Other parameters such as enabled can be provided. Return: Feature: the feature that has been initialized. """ variants = [] force_rules = [] for name, active in data.get('variants', {}).items(): variant = feature_variant_model.FeatureVariant(name, active=active) variants.append(variant) for name, force_rule in data.get('force', {}).items(): for current_force_rule in _create_force_rule_from_dictionary(name, force_rule): force_rules.append(current_force_rule) return feature_model.Feature(data.get('name'), variants, force_rules=force_rules) def _create_force_rule_from_dictionary(name, data): """Create a list of variant overrides from a dictionary. Args: name (str): the name of the variants. data (dict): the data of the overrides. Yields: FeatureVariantForceRule: the feature variant force rule. """ for filter_name, values in data.items(): filter_method = filters.get(filter_name) yield force_rule_model.FeatureVariantForceRule(name, filter_method, values)