Example #1
0
    def is_to_be_grouped(self, node):
        """
        Return whether the given node has to be included in the autogroup according to include/exclude list

        :return (bool): True if ``node`` is to be included in the autogroup
        """
        # strings, including possibly 'all'
        include = self.get_include()
        exclude = self.get_exclude()
        if include is None and exclude is None:
            # Include all classes by default if nothing is explicitly specified.
            return True

        # We should never be here, anyway - this should be catched by the `set_include/exclude` methods
        assert include is None or exclude is None, "You cannot specify both an 'include' and an 'exclude' list"

        entry_point_string = node.process_type
        # If there is no `process_type` we are dealing with a `Data` node so we get the entry point from the class
        if not entry_point_string:
            entry_point_string = get_entry_point_string_from_class(
                node.__class__.__module__, node.__class__.__name__)
        if include is not None:
            # As soon as a filter string matches, we include the class
            return any(
                self._matches(entry_point_string, filter_string)
                for filter_string in include)
        # If we are here, exclude is not None
        # include *only* in *none* of the filters match (that is, exclude as
        # soon as any of the filters matches)
        return not any(
            self._matches(entry_point_string, filter_string)
            for filter_string in exclude)
Example #2
0
    def setUpClass(cls, *args, **kwargs):
        """Define a useful CalcJobNode to test the CalcJobResultManager.

        We emulate a node for the `TemplateReplacer` calculation job class. To do this we have to make sure the
        process type is set correctly and an output parameter node is created.
        """
        super(TestCalcJobResultManager, cls).setUpClass(*args, **kwargs)
        cls.process_class = CalculationFactory('templatereplacer')
        cls.process_type = get_entry_point_string_from_class(cls.process_class.__module__, cls.process_class.__name__)
        cls.node = CalcJobNode(computer=cls.computer, process_type=cls.process_type)
        cls.node.set_option('resources', {'num_machines': 1, 'num_mpiprocs_per_machine': 1})
        cls.node.store()

        cls.key_one = 'key_one'
        cls.key_two = 'key_two'
        cls.val_one = 'val_one'
        cls.val_two = 'val_two'
        cls.keys = [cls.key_one, cls.key_two]

        cls.result_node = Dict(dict={
            cls.key_one: cls.val_one,
            cls.key_two: cls.val_two,
        }).store()

        cls.result_node.add_incoming(cls.node, LinkType.CREATE, cls.process_class.spec().default_output_node)
Example #3
0
    def test_process_class_no_default_node(self):
        """`get_results` should raise `ValueError` if process class does not define default output node."""
        # This is a valid process class however ArithmeticAddCalculation does define a default output node
        process_class = CalculationFactory('arithmetic.add')
        process_type = get_entry_point_string_from_class(process_class.__module__, process_class.__name__)
        node = CalcJobNode(computer=self.computer, process_type=process_type)

        manager = CalcJobResultManager(node)

        with self.assertRaises(ValueError):
            manager.get_results()
Example #4
0
    def _set_process_type(self, process_class):
        """
        Set the process type

        :param process_class: the process class using this calculation node as storage
        """
        class_module = process_class.__module__
        class_name = process_class.__name__

        # If the process is a registered plugin the corresponding entry point will be used as process type
        process_type = get_entry_point_string_from_class(
            class_module, class_name)

        # If no entry point was found, default to fully qualified path name
        if process_type is None:
            self.dbnode.process_type = '{}.{}'.format(class_module, class_name)
        else:
            self.dbnode.process_type = process_type
Example #5
0
    def build_process_type(cls) -> str:
        """
        The process type.

        :return: string of the process type

        Note: This could be made into a property 'process_type' but in order to have it be a property of the class
        it would need to be defined in the metaclass, see https://bugs.python.org/issue20659
        """
        from aiida.plugins.entry_point import get_entry_point_string_from_class

        class_module = cls.__module__
        class_name = cls.__name__

        # If the process is a registered plugin the corresponding entry point will be used as process type
        process_type = get_entry_point_string_from_class(class_module, class_name)

        # If no entry point was found, default to fully qualified path name
        if process_type is None:
            return f'{class_module}.{class_name}'

        return process_type
Example #6
0
    def setUpClass(cls, *args, **kwargs):
        super().setUpClass(*args, **kwargs)
        from aiida.common.links import LinkType
        from aiida.engine import ProcessState

        cls.computer = orm.Computer(name='comp',
                                    hostname='localhost',
                                    transport_type='local',
                                    scheduler_type='direct',
                                    workdir='/tmp/aiida').store()

        cls.code = orm.Code(remote_computer_exec=(cls.computer,
                                                  '/bin/true')).store()
        cls.group = orm.Group(label='test_group').store()
        cls.node = orm.Data().store()
        cls.calcs = []

        user = orm.User.objects.get_default()
        authinfo = orm.AuthInfo(computer=cls.computer, user=user)
        authinfo.store()

        process_class = CalculationFactory('templatereplacer')
        process_type = get_entry_point_string_from_class(
            process_class.__module__, process_class.__name__)

        # Create 5 CalcJobNodes (one for each CalculationState)
        for calculation_state in CalcJobState:

            calc = orm.CalcJobNode(computer=cls.computer,
                                   process_type=process_type)
            calc.set_option('resources', {
                'num_machines': 1,
                'num_mpiprocs_per_machine': 1
            })
            calc.store()

            calc.set_process_state(ProcessState.RUNNING)
            cls.calcs.append(calc)

            if calculation_state == CalcJobState.PARSING:
                cls.KEY_ONE = 'key_one'
                cls.KEY_TWO = 'key_two'
                cls.VAL_ONE = 'val_one'
                cls.VAL_TWO = 'val_two'

                output_parameters = orm.Dict(dict={
                    cls.KEY_ONE: cls.VAL_ONE,
                    cls.KEY_TWO: cls.VAL_TWO,
                }).store()

                output_parameters.add_incoming(calc, LinkType.CREATE,
                                               'output_parameters')

                # Create shortcut for easy dereferencing
                cls.result_job = calc

                # Add a single calc to a group
                cls.group.add_nodes([calc])

        # Create a single failed CalcJobNode
        cls.EXIT_STATUS = 100
        calc = orm.CalcJobNode(computer=cls.computer)
        calc.set_option('resources', {
            'num_machines': 1,
            'num_mpiprocs_per_machine': 1
        })
        calc.store()
        calc.set_exit_status(cls.EXIT_STATUS)
        calc.set_process_state(ProcessState.FINISHED)
        cls.calcs.append(calc)

        # Load the fixture containing a single ArithmeticAddCalculation node
        import_archive('calcjob/arithmetic.add.aiida')

        # Get the imported ArithmeticAddCalculation node
        ArithmeticAddCalculation = CalculationFactory('arithmetic.add')
        calculations = orm.QueryBuilder().append(
            ArithmeticAddCalculation).all()[0]
        cls.arithmetic_job = calculations[0]