Skip to content
3 changes: 3 additions & 0 deletions smartsim/launchable/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from .basejob import BaseJob
from .baseJobGroup import BaseJobGroup
from .colocatedJobGroup import ColocatedJobGroup
from .job import Job
from .jobGroup import JobGroup
from .launchable import Launchable
from .mpmdjob import MPMDJob
from .mpmdpair import MPMDPair
58 changes: 58 additions & 0 deletions smartsim/launchable/baseJobGroup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import typing as t
from abc import abstractmethod
from collections.abc import MutableSequence
from copy import deepcopy

from smartsim.launchable.launchable import Launchable

from .basejob import BaseJob


class BaseJobGroup(Launchable, MutableSequence):
"""Highest level ABC of a group of jobs that can be
launched
"""

def __init__(self) -> None:
super().__init__()

@property
@abstractmethod
def jobs(self) -> t.List[BaseJob]:
"""This property method returns a list of BaseJob objects.
It represents the collection of jobs associated with an
instance of the BaseJobGroup abstract class.
"""
pass

def insert(self, idx: int, value: BaseJob) -> None:
"""Inserts the given value at the specified index (idx) in
the list of jobs. If the index is out of bounds, the method
prints an error message.
"""
self.jobs.insert(idx, value)

def __iter__(self) -> t.Iterator[BaseJob]:
"""Allows iteration over the jobs in the collection."""
return iter(self.jobs)

def __getitem__(self, idx: int) -> BaseJob:
"""Retrieves the job at the specified index (idx)."""
return self.jobs[idx]

def __setitem__(self, idx: int, value: BaseJob) -> None:
"""Sets the job at the specified index (idx) to the given value."""
self.jobs[idx] = deepcopy(value)

def __delitem__(self, idx: int) -> None:
"""Deletes the job at the specified index (idx)."""
del self.jobs[idx]

def __len__(self) -> int:
"""Returns the total number of jobs in the collection."""
return len(self.jobs)

def __str__(self): # pragma: no-cover
"""Returns a string representation of the collection of jobs."""
string = ""
string += f"Jobs: {self.jobs}"
1 change: 0 additions & 1 deletion smartsim/launchable/basejob.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
class BaseJob(ABC, Launchable):
"""The highest level abstract base class for a single job that can be launched"""

@abstractmethod
def get_launch_steps(self) -> None: # TODO: -> LaunchSteps:
"""Return the launch steps corresponding to the
internal data.
Expand Down
34 changes: 34 additions & 0 deletions smartsim/launchable/colocatedJobGroup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import typing as t
from copy import deepcopy

from .basejob import BaseJob
from .baseJobGroup import BaseJobGroup


class ColocatedJobGroup(BaseJobGroup):
"""A colocated job group holds references to multiple jobs that
will be executed all at the same time when resources
permit. Execution is blocked until resources are available.
"""

def __init__(
self,
jobs: t.List[BaseJob],
) -> None:
super().__init__()
self._jobs = deepcopy(jobs)

@property
def jobs(self) -> t.List[BaseJob]:
"""This property method returns a list of BaseJob objects.
It represents the collection of jobs associated with an
instance of the BaseJobGroup abstract class.
"""
return self._jobs

def __str__(self): # pragma: no-cover
"""Returns a string representation of the collection of
colocated job groups.
"""
string = ""
string += f"Colocated Jobs: {self.jobs}"
34 changes: 34 additions & 0 deletions smartsim/launchable/jobGroup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import typing as t
from copy import deepcopy

from .basejob import BaseJob
from .baseJobGroup import BaseJobGroup


class JobGroup(BaseJobGroup):
"""A job group holds references to multiple jobs that
will be executed all at the same time when resources
permit. Execution is blocked until resources are available.
"""

def __init__(
self,
jobs: t.List[BaseJob],
) -> None:
super().__init__()
self._jobs = deepcopy(jobs)

@property
def jobs(self) -> t.List[BaseJob]:
"""This property method returns a list of BaseJob objects.
It represents the collection of jobs associated with an
instance of the BaseJobGroup abstract class.
"""
return self._jobs

def __str__(self): # pragma: no-cover
"""Returns a string representation of the collection of
job groups.
"""
string = ""
string += f"Job Groups: {self.jobs}"
6 changes: 4 additions & 2 deletions smartsim/launchable/mpmdpair.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import copy

from smartsim.entity.entity import SmartSimEntity
from smartsim.settings.base import RunSettings

Expand All @@ -34,5 +36,5 @@ class MPMDPair:
def __init__(
self, entity: SmartSimEntity, launch_settings: RunSettings
): # TODO: rename to LaunchSettings
self.entity = entity
self.launch_settings = launch_settings
self.entity = copy.deepcopy(entity)
self.launch_settings = copy.deepcopy(launch_settings)
61 changes: 61 additions & 0 deletions tests/temp_tests/test_colocatedJobGroup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from smartsim.entity.model import Application
from smartsim.launchable.basejob import BaseJob
from smartsim.launchable.colocatedJobGroup import ColocatedJobGroup
from smartsim.launchable.job import Job
from smartsim.settings.base import RunSettings

# TODO replace with LaunchSettings
app_1 = Application("app_1", "python", run_settings=RunSettings())
app_2 = Application("app_2", "python", run_settings=RunSettings())
app_3 = Application("app_3", "python", run_settings=RunSettings())


def test_create_ColocatedJobGroup():
job_1 = BaseJob()
job_group = ColocatedJobGroup([job_1])
assert len(job_group) == 1


def test_getitem_ColocatedJobGroup():
job_1 = Job(app_1, RunSettings())
job_2 = Job(app_2, RunSettings())
job_group = ColocatedJobGroup([job_1, job_2])
get_value = job_group[0].entity.name
assert get_value == job_1.entity.name


def test_setitem_JobGroup():
job_1 = Job(app_1, RunSettings())
job_2 = Job(app_2, RunSettings())
job_group = ColocatedJobGroup([job_1, job_2])
job_3 = Job(app_3, RunSettings())
job_group[1] = job_3
assert len(job_group) == 2
get_value = job_group[1].entity.name
assert get_value == job_3.entity.name


def test_delitem_ColocatedJobGroup():
job_1 = BaseJob()
job_2 = BaseJob()
job_group = ColocatedJobGroup([job_1, job_2])
assert len(job_group) == 2
del job_group[1]
assert len(job_group) == 1


def test_len_ColocatedJobGroup():
job_1 = BaseJob()
job_2 = BaseJob()
job_group = ColocatedJobGroup([job_1, job_2])
assert len(job_group) == 2


def test_insert_ColocatedJobGroup():
job_1 = BaseJob()
job_2 = BaseJob()
job_group = ColocatedJobGroup([job_1, job_2])
job_3 = BaseJob()
job_group.insert(0, job_3)
get_value = job_group[0]
assert get_value == job_3
61 changes: 61 additions & 0 deletions tests/temp_tests/test_jobGroup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from smartsim.entity.model import Application
from smartsim.launchable.basejob import BaseJob
from smartsim.launchable.job import Job
from smartsim.launchable.jobGroup import JobGroup
from smartsim.settings.base import RunSettings

# TODO replace with LaunchSettings
app_1 = Application("app_1", "python", RunSettings())
app_2 = Application("app_2", "python", RunSettings())
app_3 = Application("app_3", "python", RunSettings())


def test_create_JobGroup():
job_1 = BaseJob()
job_group = JobGroup([job_1])
assert len(job_group) == 1


def test_getitem_JobGroup():
job_1 = Job(app_1, RunSettings())
job_2 = Job(app_2, RunSettings())
job_group = JobGroup([job_1, job_2])
get_value = job_group[0].entity.name
assert get_value == job_1.entity.name


def test_setitem_JobGroup():
job_1 = Job(app_1, RunSettings())
job_2 = Job(app_2, RunSettings())
job_group = JobGroup([job_1, job_2])
job_3 = Job(app_3, RunSettings())
job_group[1] = job_3
assert len(job_group) == 2
get_value = job_group[1]
assert get_value.entity.name == job_3.entity.name


def test_delitem_JobGroup():
job_1 = BaseJob()
job_2 = BaseJob()
job_group = JobGroup([job_1, job_2])
assert len(job_group) == 2
del job_group[1]
assert len(job_group) == 1


def test_len_JobGroup():
job_1 = BaseJob()
job_2 = BaseJob()
job_group = JobGroup([job_1, job_2])
assert len(job_group) == 2


def test_insert_JobGroup():
job_1 = BaseJob()
job_2 = BaseJob()
job_group = JobGroup([job_1, job_2])
job_3 = BaseJob()
job_group.insert(0, job_3)
get_value = job_group[0]
assert get_value == job_3
Loading