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

BaseJobGroup, JobGroup, ColocatedJobGroup skeleton #599

Merged
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__()

Check warning on line 17 in smartsim/launchable/baseJobGroup.py

View check run for this annotation

Codecov / codecov/patch

smartsim/launchable/baseJobGroup.py#L17

Added line #L17 was not covered by tests

@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)

Check warning on line 33 in smartsim/launchable/baseJobGroup.py

View check run for this annotation

Codecov / codecov/patch

smartsim/launchable/baseJobGroup.py#L33

Added line #L33 was not covered by tests

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

Check warning on line 37 in smartsim/launchable/baseJobGroup.py

View check run for this annotation

Codecov / codecov/patch

smartsim/launchable/baseJobGroup.py#L37

Added line #L37 was not covered by tests

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

Check warning on line 41 in smartsim/launchable/baseJobGroup.py

View check run for this annotation

Codecov / codecov/patch

smartsim/launchable/baseJobGroup.py#L41

Added line #L41 was not covered by tests

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)

Check warning on line 45 in smartsim/launchable/baseJobGroup.py

View check run for this annotation

Codecov / codecov/patch

smartsim/launchable/baseJobGroup.py#L45

Added line #L45 was not covered by tests

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

Check warning on line 49 in smartsim/launchable/baseJobGroup.py

View check run for this annotation

Codecov / codecov/patch

smartsim/launchable/baseJobGroup.py#L49

Added line #L49 was not covered by tests

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

Check warning on line 53 in smartsim/launchable/baseJobGroup.py

View check run for this annotation

Codecov / codecov/patch

smartsim/launchable/baseJobGroup.py#L53

Added line #L53 was not covered by tests

def __str__(self): # pragma: no-cover
"""Returns a string representation of the collection of jobs."""
string = ""
string += f"Jobs: {self.jobs}"

Check warning on line 58 in smartsim/launchable/baseJobGroup.py

View check run for this annotation

Codecov / codecov/patch

smartsim/launchable/baseJobGroup.py#L57-L58

Added lines #L57 - L58 were not covered by tests
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)

Check warning on line 19 in smartsim/launchable/colocatedJobGroup.py

View check run for this annotation

Codecov / codecov/patch

smartsim/launchable/colocatedJobGroup.py#L18-L19

Added lines #L18 - L19 were not covered by tests

@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

Check warning on line 27 in smartsim/launchable/colocatedJobGroup.py

View check run for this annotation

Codecov / codecov/patch

smartsim/launchable/colocatedJobGroup.py#L27

Added line #L27 was not covered by tests

def __str__(self): # pragma: no-cover
"""Returns a string representation of the collection of
colocated job groups.
"""
string = ""
string += f"Colocated Jobs: {self.jobs}"

Check warning on line 34 in smartsim/launchable/colocatedJobGroup.py

View check run for this annotation

Codecov / codecov/patch

smartsim/launchable/colocatedJobGroup.py#L33-L34

Added lines #L33 - L34 were not covered by tests
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)

Check warning on line 19 in smartsim/launchable/jobGroup.py

View check run for this annotation

Codecov / codecov/patch

smartsim/launchable/jobGroup.py#L18-L19

Added lines #L18 - L19 were not covered by tests

@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

Check warning on line 27 in smartsim/launchable/jobGroup.py

View check run for this annotation

Codecov / codecov/patch

smartsim/launchable/jobGroup.py#L27

Added line #L27 was not covered by tests

def __str__(self): # pragma: no-cover
"""Returns a string representation of the collection of
job groups.
"""
string = ""
string += f"Job Groups: {self.jobs}"

Check warning on line 34 in smartsim/launchable/jobGroup.py

View check run for this annotation

Codecov / codecov/patch

smartsim/launchable/jobGroup.py#L33-L34

Added lines #L33 - L34 were not covered by tests
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 @@
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)

Check warning on line 40 in smartsim/launchable/mpmdpair.py

View check run for this annotation

Codecov / codecov/patch

smartsim/launchable/mpmdpair.py#L39-L40

Added lines #L39 - L40 were not covered by tests
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
Loading