Exemple #1
0
 def action_register(self, rendered_action_data, action_data):
     """Register arbitrary items to the registry"""
     for key, value in remove_keys(
         rendered_action_data, 'loop_index'
     ).items():
         data = remove_keys(action_data.copy(), 'loop_index')
         data['register'] = key
         self.add_to_registry(data, value)
Exemple #2
0
    def add_rendered_action(self, action_data, rendered_action_data):
        """Add rendered action to be written in validation file"""
        data = remove_keys(
            action_data, 'loop_index', '_values', 'log_message',
            deep=True
        )

        def persist_factory(a_dict):
            """Generated data should be persisted in validation file"""
            for k, v in a_dict.items():
                if not isinstance(v, dict):
                    continue
                if 'from_factory' in v:
                    a_dict[k] = rendered_action_data[k]
                else:
                    persist_factory(v)

        persist_factory(data)
        if data.get('with_items'):
            data['loop_index'] = rendered_action_data['loop_index']

        self.rendered_actions.append(data)
def save_rendered_data(result, filepath):
    """Save the result of rendering in a new file to be used for
    validation"""
    file_format = os.path.splitext(filepath)[-1]
    if file_format not in ('.json', '.yml', '.yaml', '.py'):
        raise ValueError("Invalid filename extension")

    data = OrderedDict({
        'input_filename': result.input_filename,
        'config': dict(result.config),
        'vars': dict(result.vars),
        'actions': result.rendered_actions
    })

    data['config']['mode'] = 'validate'
    data['config'] = remove_keys(data['config'], 'output')
    # should remove username, password, hostname ?

    data['config'] = remove_nones(data['config'])

    directory, filename = os.path.split(filepath)

    if not directory and data.get('input_filename'):
        directory = os.path.dirname(result.input_filename)

    if not filename.startswith('validation'):
        filename = "validation_{0}".format(filename)

    filepath = os.path.join(directory, filename)

    with open(filepath, 'w') as output:
        if file_format in ('.yml', '.yaml'):
            output.write(yaml.dump(data))
        elif file_format == '.json':
            output.write(json.dumps(data, indent=4))
        elif file_format == '.py':
            output.write("data = {0}".format(pformat(dict(data))))

    result.logger.debug("Validation data saved in %s", filepath)
Exemple #4
0
def save_rendered_data(result, filepath):
    """Save the result of rendering in a new file to be used for
    validation"""
    file_format = os.path.splitext(filepath)[-1]
    if file_format not in ('.json', '.yml', '.yaml', '.py'):
        raise ValueError("Invalid filename extension")

    data = OrderedDict({
        'input_filename': result.input_filename,
        'config': dict(result.config),
        'vars': dict(result.vars),
        'actions': result.rendered_actions
    })

    data['config']['mode'] = 'validate'
    data['config'] = remove_keys(data['config'], 'output')
    # should remove username, password, hostname ?

    data['config'] = remove_nones(data['config'])

    directory, filename = os.path.split(filepath)

    if not directory and data.get('input_filename'):
        directory = os.path.dirname(result.input_filename)

    if not filename.startswith('validation'):
        filename = "validation_{0}".format(filename)

    filepath = os.path.join(directory, filename)

    with open(filepath, 'w') as output:
        if file_format in ('.yml', '.yaml'):
            output.write(yaml.dump(data))
        elif file_format == '.json':
            output.write(json.dumps(data, indent=4))
        elif file_format == '.py':
            output.write("data = {0}".format(pformat(dict(data))))

    result.logger.debug("Validation data saved in %s", filepath)
Exemple #5
0
    def build_search(self, rendered_action_data, action_data, context=None):
        """Build search data and returns a dict containing elements

        - data
          Dictionary of parsed rendered_action_data to be used to i
          nstantiate an object to searched without raw_query.

        - options
          if `search_options` are specified it is passed to
          `.search(**options)`

        - searchable
          Returns boolean True if model inherits from EntitySearchMixin, else
          alternative search must be implemented.

        if `search_query` is available in action_data it will be used instead
        of rendered_action_data.
        """

        # if with_items, get current loop_index reference or 0
        loop_index = rendered_action_data.get('loop_index', 0)

        if 'search_query' not in action_data:
            data = rendered_action_data
        else:
            search_data = action_data['search_query']
            if isinstance(search_data, dict):
                items = action_data.get('with_items')

                if items and isinstance(items, list):
                    items = [
                        Template(item).render(**self.context)
                        for item in items
                    ]
                elif items and isinstance(items, string_types):
                    items = eval(items, None, self.context)
                    if not isinstance(items, Sequence):
                        raise AttributeError(
                            "with_items must be sequence type")
                else:
                    # as there is no with_items, a single item list will
                    # ensure the addition of a single one.
                    items = [None, ]

                new_context = {}
                new_context.update(self.context)
                new_context.update(context or {})
                new_context['item'] = items[loop_index]
                new_context['loop_index'] = loop_index
                data = search_data.copy()
                self.render_action_data(data, new_context)

            elif isinstance(search_data, Sequence):
                data = {
                    key: rendered_action_data[key]
                    for key in search_data
                }
            else:
                raise ValueError("search_query bad formatted")

        model_name = action_data['model']
        model = getattr(entities, model_name)

        data = remove_keys(data, 'loop_index')

        options = self.build_search_options(data, action_data)

        # force_raw = action_data.get(
        #     'force_raw', False
        # ) or action_data['model'].lower() in self.force_raw_search

        search = {
            'data': data,
            'options': options,
            'searchable': issubclass(model, EntitySearchMixin)
        }

        return search
Exemple #6
0
    def execute(self, mode=None):
        """Iterates the entities property described in YAML file
        and parses its values, variables and substitutions
        depending on `mode` execute `populate` or `validate`
        """
        mode = mode or self.mode
        self.logger.info("Starting in %s mode", mode)
        for action_data in self.actions:
            action = action_data.get('action', 'create')

            if action_data.get('when'):
                if not eval(action_data.get('when'), None, self.context):
                    continue

            log_message = action_data['log_message'] = Template(
                action_data.get(
                    'log', action_data.get('register', 'executing...')
                )
            ).render(**self.context)

            getattr(self.logger, action_data.get('level', 'info').lower())(
                '%s: %s',
                action.upper() if not (
                    mode == 'validate' and action == 'create'
                ) else "VALIDATE",
                log_message
            )

            actions_list = self.render(action_data, action)
            for rendered_action_data in actions_list:

                if action not in self.crud_actions:
                    # find the method named as action_name
                    action_name = "action_{0}".format(action.lower())
                    getattr(self, action_name)(
                        rendered_action_data,
                        action_data
                    )

                    self.context.update(self.registry)

                    # check if it is better to do that in method
                    self.add_rendered_action(action_data, rendered_action_data)

                    # execute above method and continue to next item
                    continue

                # Executed only for crud_actions
                model_name = action_data['model'].lower()
                method = getattr(
                    self, '{0}_{1}'.format(mode, model_name), None
                )
                search = self.build_search(
                    rendered_action_data, action_data
                )

                entity_data = remove_keys(
                    rendered_action_data, 'loop_index'
                )

                if method:
                    method(entity_data, action_data, search, action)
                else:
                    # execute self.populate or self.validate
                    getattr(self, mode)(
                        entity_data, action_data, search, action
                    )

                # ensure context is updated with latest created entities
                self.context.update(self.registry)

                self.add_rendered_action(
                    action_data, rendered_action_data
                )