コード例 #1
0
ファイル: parsing.py プロジェクト: playpauseandstop/setman
def parse_configs(framework):
    """
    Parse all available config definition files as for all availbale apps and
    for project itself at last.

    Also we need to read additional types and additional default values before
    parsing start.
    """
    additional_types = framework.get_additional_types()
    all_settings = SettingsContainer()
    default_values = {}
    fail_silently = framework.fail_silently

    # Use ``OrderedDict`` instance for reading sections on config file instead
    # of default ``dict`` that can shuffle the sections.
    config = ConfigParser(dict_type=OrderedDict)

    # First we need to read default values file
    default_values_file = framework.find_default_values_file()

    if default_values_file:
        config.no_sections_mode = True

        try:
            config.read(default_values_file)
        except ConfigParserError:
            logger.exception('Cannot read default values from %r',
                             default_values_file)
        else:
            default_values = config.defaults()
        finally:
            config.no_sections_mode = False

    # Read available settings files from framework
    pathes = framework.find_settings_files()

    for app_name, path in pathes.items():
        if app_name == '__project__':
            continue

        settings = \
            parse_config(path, additional_types, default_values, app_name)
        all_settings.add(app_name, settings)

    # And finally read project configuration definition file if any
    path = pathes.get('__project__')

    settings = parse_config(path, additional_types, default_values,
                            all_settings=all_settings)
    all_settings.add('__project__', settings)
    all_settings.path = settings.path

    return all_settings
コード例 #2
0
    def get_additional_types(self):
        """
        Return tuple of additional types that would be supported when parsing
        config definition files.
        """
        additional_types = self.additional_types or ()
        types = []

        for item in additional_types:
            try:
                additional_type = load_from_path(item)
            except (AttributeError, TypeError):
                logger.exception("Cannot load %r additional setting type " "from configuration", item)
                continue

            types.append(additional_type)

        return tuple(types)
コード例 #3
0
    def _parse_validators(self, value):
        """
        Parse validators string and try to convert it to list with actual
        validator functions.
        """
        if not value:
            return []

        items = map(lambda item: item.strip(), value.split(','))
        validators = []

        for item in items:
            try:
                validator = load_from_path(item)
            except (AttributeError, ImportError):
                logger.exception('Cannot load %r validator for %s setting.',
                                 item, self.name)
                continue

            validators.append(validator)

        return validators
コード例 #4
0
ファイル: types.py プロジェクト: macanhhuy/setman
    def _parse_validators(self, value):
        """
        Parse validators string and try to convert it to list with actual
        validator functions.
        """
        if not value:
            return []

        items = map(lambda item: item.strip(), value.split(','))
        validators = []

        for item in items:
            try:
                validator = load_from_path(item)
            except (AttributeError, ImportError):
                logger.exception('Cannot load %r validator for %s setting.',
                                 item, self.name)
                continue

            validators.append(validator)

        return validators
コード例 #5
0
    def _parse_choices(self, value):
        """
        Convert string value to valid choices tuple.

        **Supported formats:**

        * a, b, c
        * (a, A), (b, B), (c, C)
        * a { b, c }, d { e, f }
        * A { (b, B), (c, C) }, D { (e, E), (f, F) }
        * path.to.CHOICES
        * path.to.Model.CHOICES

        """
        # Start parsing with internal choices
        if not ',' in value and '.' in value:
            # Choices tuple should be last part of value
            path, attr = value.rsplit('.', 1)

            # Load choices from module
            try:
                module = importlib.import_module(path)
            except ImportError:
                # Or from module class
                try:
                    module = load_from_path(path)
                except (AttributeError, ImportError):
                    logger.exception('Cannot load choices from %r path', value)
                    return ()

            # Try to get choices attr in module
            try:
                choices = getattr(module, attr)
            except AttributeError:
                logger.exception('Cannot load choices from %r path', value)
                return ()
        elif not '{' in value and not '}' in value:
            # Parse choice with labels
            label_re = re.compile(r'\(([^,]+),\s+([^\)]+)\)', re.M)
            found = label_re.findall(value)

            if found:
                choices = found
            # If nothing found by regex, just split value by comma and
            # duplicate resulted items
            else:
                choices = map(lambda item: (item.strip(), item.strip()),
                              value.split(','))
        else:
            # Parse groups
            groups_re = re.compile(r'([^{]+){([^}]+)},?', re.M)
            found = groups_re.findall(value)

            if found:
                choices = []

                for group, data in found:
                    group = group.strip()
                    choices.append((group, self._parse_choices(data.strip())))
            else:
                logger.error('Cannot parse choices from %r', value)
                return ()

        return tuple(choices)
コード例 #6
0
ファイル: parsing.py プロジェクト: playpauseandstop/setman
def parse_config(path, additional_types=None, default_values=None,
                 app_name=None, all_settings=None):
    """
    Parse Configuration Definition File.

    In most cases this file needs to be placed in same folder where project
    settings module exist and named as ``settings.cfg``.

    But you can customize things with using ``SETMAN_SETTINGS_FILE`` option.
    Provide there path where settings file actually placed.

    Also current function can called with ``path`` string.
    """
    config = ConfigParser(dict_type=OrderedDict)
    empty_settings = SettingsContainer(path, app_name)

    try:
        config.read(path)
    except ConfigParserError:
        logger.exception('Cannot parse configuration definition file from ' \
                         '%r', path)
        return empty_settings

    settings = copy.deepcopy(empty_settings)

    for setting in config.sections():
        if '.' in setting:
            full_setting = setting
            app_name, setting = setting.split('.', 1)

            try:
                app_settings = getattr(all_settings, app_name)
            except AttributeError:
                logger.exception('Cannot find settings for %r app', app_name)
                continue

            try:
                app_setting = getattr(app_settings, setting)
            except AttributeError:
                logger.exception('Cannot find %r app setting %r',
                                 app_name, setting)
                continue

            data = dict(config.items(full_setting))

            if default_values and full_setting in default_values:
                data.update({'default': default_values[setting]})

            try:
                app_setting = update_app_setting(app_setting, data)
            except ValueError:
                logger.exception('Cannot redefine ``type`` attr for %r ' \
                                 'setting', full_setting)
                continue
        else:
            data = dict(config.items(setting))
            data.update({'app_name': app_name, 'name': setting})

            if default_values and setting in default_values:
                data.update({'default': default_values[setting]})

            try:
                setting = data_to_setting(data, additional_types)
            except SettingTypeDoesNotExist:
                logger.exception('Cannot find proper setting class for %r ' \
                                 'type', data.get('type'))
                return empty_settings

            settings.add(setting.name, setting)

    return settings
コード例 #7
0
ファイル: types.py プロジェクト: macanhhuy/setman
    def _parse_choices(self, value):
        """
        Convert string value to valid choices tuple.

        **Supported formats:**

        * a, b, c
        * (a, A), (b, B), (c, C)
        * a { b, c }, d { e, f }
        * A { (b, B), (c, C) }, D { (e, E), (f, F) }
        * path.to.CHOICES
        * path.to.Model.CHOICES

        """
        # Start parsing with internal choices
        if not ',' in value and '.' in value:
            # Choices tuple should be last part of value
            path, attr = value.rsplit('.', 1)

            # Load choices from module
            try:
                module = importlib.import_module(path)
            except ImportError:
                # Or from module class
                try:
                    module = load_from_path(path)
                except (AttributeError, ImportError):
                    logger.exception('Cannot load choices from %r path',
                                     value)
                    return ()

            # Try to get choices attr in module
            try:
                choices = getattr(module, attr)
            except AttributeError:
                logger.exception('Cannot load choices from %r path', value)
                return ()
        elif not '{' in value and not '}' in value:
            # Parse choice with labels
            label_re = re.compile(r'\(([^,]+),\s+([^\)]+)\)', re.M)
            found = label_re.findall(value)

            if found:
                choices = found
            # If nothing found by regex, just split value by comma and
            # duplicate resulted items
            else:
                choices = map(lambda item: (item.strip(), item.strip()),
                              value.split(','))
        else:
            # Parse groups
            groups_re = re.compile(r'([^{]+){([^}]+)},?', re.M)
            found = groups_re.findall(value)

            if found:
                choices = []

                for group, data in found:
                    group = group.strip()
                    choices.append((group, self._parse_choices(data.strip())))
            else:
                logger.error('Cannot parse choices from %r', value)
                return ()

        return tuple(choices)