Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attmpt to decouple this_code setup #5664

Merged
merged 9 commits into from
Sep 27, 2022
Merged
10 changes: 5 additions & 5 deletions aiida/engine/processes/calcjobs/calcjob.py
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ def presubmit(self, folder: Folder) -> CalcInfo:
from aiida.common.datastructures import CodeInfo, CodeRunMode
from aiida.common.exceptions import InputValidationError, InvalidOperation, PluginInternalError, ValidationError
from aiida.common.utils import validate_list_of_string_tuples
from aiida.orm import AbstractCode, Code, Computer, InstalledCode, PortableCode, load_node
from aiida.orm import AbstractCode, Computer, PortableCode, load_code
from aiida.schedulers.datastructures import JobTemplate, JobTemplateCodeInfo

inputs = self.node.base.links.get_incoming(link_type=LinkType.INPUT_CALC)
Expand Down Expand Up @@ -719,7 +719,7 @@ def presubmit(self, folder: Folder) -> CalcInfo:

if code_info.code_uuid is None:
raise PluginInternalError('CalcInfo should have the information of the code to be launched')
this_code = load_node(code_info.code_uuid, sub_classes=(Code, InstalledCode, PortableCode))
this_code = load_code(code_info.code_uuid)

# To determine whether this code should be run with MPI enabled, we get the value that was set in the inputs
# of the entire process, which can then be overwritten by the value from the `CodeInfo`. This allows plugins
Expand All @@ -734,11 +734,11 @@ def presubmit(self, folder: Folder) -> CalcInfo:
this_withmpi = code_info.withmpi

if this_withmpi:
prepend_cmdline_params = mpi_args + extra_mpirun_params
prepend_cmdline_params = this_code.get_prepend_cmdline_params(mpi_args, extra_mpirun_params)
else:
prepend_cmdline_params = []
prepend_cmdline_params = this_code.get_prepend_cmdline_params()

cmdline_params = [str(this_code.get_executable())] + (code_info.cmdline_params or [])
cmdline_params = this_code.get_executable_cmdline_params(code_info.cmdline_params)

tmpl_code_info = JobTemplateCodeInfo()
tmpl_code_info.prepend_cmdline_params = prepend_cmdline_params
Expand Down
31 changes: 29 additions & 2 deletions aiida/orm/nodes/data/code/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import abc
import collections
import pathlib

import click

Expand Down Expand Up @@ -70,12 +71,38 @@ def can_run_on_computer(self, computer: Computer) -> bool:
"""

@abc.abstractmethod
def get_executable(self) -> str:
"""Return the executable that the submission script should execute to run the code.
def get_executable(self) -> pathlib.Path:
"""
Return the executable that the submission script should execute to run the code.
unkcpz marked this conversation as resolved.
Show resolved Hide resolved

:return: The executable to be called in the submission script.
"""

def get_executable_cmdline_params(self, cmdline_params: list[str] | None = None) -> list:
"""
Return the list of executable with its command line parameters.
unkcpz marked this conversation as resolved.
Show resolved Hide resolved

:param cmdline_params: List of command line parameters provided by the ``CalcJob`` plugin.
:return: List of the executable followed by its command line parameters.
"""
return [str(self.get_executable())] + (cmdline_params or [])

def get_prepend_cmdline_params( # pylint: disable=no-self-use
self,
mpi_args: list[str] | None = None,
extra_mpirun_params: list[str] | None = None
) -> list[str]:
"""
Return List of command line parameters to be prepended to the executable in submission line.
unkcpz marked this conversation as resolved.
Show resolved Hide resolved
These command line parameters are typically parameters related to MPI invocations.

:param mpi_args: List of MPI parameters provided by the ``Computer.get_mpirun_command`` method.
:param extra_mpiruns_params: List of MPI parameters provided by the ``metadata.options.extra_mpirun_params``
input of the ``CalcJob``.
:return: List of command line parameters to be prepended to the executable in submission line.
"""
return (mpi_args or []) + (extra_mpirun_params or [])

@property
@abc.abstractmethod
def full_label(self) -> str:
Expand Down
2 changes: 1 addition & 1 deletion aiida/orm/nodes/data/code/installed.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def can_run_on_computer(self, computer: Computer) -> bool:
type_check(computer, Computer)
return computer.pk == self.computer.pk

def get_executable(self) -> str:
def get_executable(self) -> pathlib.Path:
"""Return the executable that the submission script should execute to run the code.

:return: The executable to be called in the submission script.
Expand Down
9 changes: 6 additions & 3 deletions aiida/orm/nodes/data/code/legacy.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
###########################################################################
"""Data plugin represeting an executable code to be wrapped and called through a `CalcJob` plugin."""
import os
import pathlib

from aiida.common import exceptions
from aiida.common.log import override_log_level
Expand Down Expand Up @@ -78,15 +79,17 @@ def can_run_on_computer(self, computer: Computer) -> bool:
type_check(computer, orm.Computer)
return computer.pk == self.get_remote_computer().pk

def get_executable(self) -> str:
def get_executable(self) -> pathlib.Path:
"""Return the executable that the submission script should execute to run the code.

:return: The executable to be called in the submission script.
"""
if self.is_local():
return f'./{self.get_local_executable()}'
exec_path = f'./{self.get_local_executable()}'

return self.get_remote_exec_path()
exec_path = self.get_remote_exec_path()

return pathlib.Path(exec_path)

def hide(self):
"""
Expand Down
2 changes: 1 addition & 1 deletion aiida/orm/nodes/data/code/portable.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def can_run_on_computer(self, computer: Computer) -> bool:
"""
return True

def get_executable(self) -> str:
def get_executable(self) -> pathlib.Path:
"""Return the executable that the submission script should execute to run the code.

:return: The executable to be called in the submission script.
Expand Down
2 changes: 1 addition & 1 deletion aiida/orm/utils/builders/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def get_code_spec(code):
else:
spec['code_type'] = CodeBuilder.CodeType.ON_COMPUTER
spec['computer'] = code.computer
spec['remote_abs_path'] = code.get_executable()
spec['remote_abs_path'] = str(code.get_executable())

return spec

Expand Down
4 changes: 3 additions & 1 deletion tests/orm/data/code/test_abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
###########################################################################
# pylint: disable=redefined-outer-name
"""Tests for the :class:`aiida.orm.nodes.data.code.abstract.AbstractCode` class."""
import pathlib

import pytest

from aiida.orm.nodes.data.code.abstract import AbstractCode
Expand All @@ -21,7 +23,7 @@ def can_run_on_computer(self, computer) -> bool:
"""Return whether the code can run on a given computer."""
return True

def get_executable(self) -> str:
def get_executable(self) -> pathlib.Path:
"""Return the executable that the submission script should execute to run the code."""
return ''

Expand Down