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

Print attached files #352

Merged
merged 6 commits into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions smartsim/entity/ensemble.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
from copy import deepcopy
from os import getcwd

from tabulate import tabulate

from .._core.utils.helpers import init_default
from ..error import (
EntityExistsError,
Expand Down Expand Up @@ -275,6 +277,30 @@ def attach_generator_files(
to_copy=to_copy, to_symlink=to_symlink, to_configure=to_configure
)

@property
def attached_files_table(self) -> str:
"""Return a plain-text table with information about files
attached to models belonging to this ensemble.

:returns: A table of all files attached to all models
:rtype: str
al-rigazzi marked this conversation as resolved.
Show resolved Hide resolved
"""
if not self.models:
return "The ensemble is empty, no files to show."

values = []
for model in self.models:
values.append([model.name, model.attached_files_table])

table = tabulate(values, headers=["Model name", "Files"], tablefmt="grid")
al-rigazzi marked this conversation as resolved.
Show resolved Hide resolved

return table

def print_attached_files(self) -> None:
"""Print table of attached files to std out
"""
print(self.attached_files_table)

@staticmethod
def _set_strategy(strategy: str) -> StrategyFunction:
"""Set the permutation strategy for generating models within
Expand Down Expand Up @@ -335,7 +361,7 @@ def add_ml_model(
backend: str,
model: t.Optional[str] = None,
model_path: t.Optional[str] = None,
device: t.Literal["CPU","GPU"] = "CPU",
device: t.Literal["CPU", "GPU"] = "CPU",
devices_per_node: int = 1,
batch_size: int = 0,
min_batch_size: int = 0,
Expand Down Expand Up @@ -395,7 +421,7 @@ def add_script(
name: str,
script: t.Optional[str] = None,
script_path: t.Optional[str] = None,
device: t.Literal["CPU","GPU"] = "CPU",
device: t.Literal["CPU", "GPU"] = "CPU",
devices_per_node: int = 1,
) -> None:
"""TorchScript to launch with every entity belonging to this ensemble
Expand Down Expand Up @@ -439,7 +465,7 @@ def add_function(
self,
name: str,
function: t.Optional[str] = None,
device: t.Literal["CPU","GPU"] = "CPU",
device: t.Literal["CPU", "GPU"] = "CPU",
devices_per_node: int = 1,
) -> None:
"""TorchScript function to launch with every entity belonging to this ensemble
Expand Down
17 changes: 17 additions & 0 deletions smartsim/entity/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import typing as t

from os import path
from tabulate import tabulate


class EntityFiles:
Expand Down Expand Up @@ -139,6 +140,22 @@ def _check_path(file_path: str) -> str:
return full_path
raise FileNotFoundError(f"File or Directory {file_path} not found")

def __str__(self) -> str:
"""Return table summarizing attached files."""
values = []

if self.copy:
values.append(["Copy", "\n".join(self.copy)])
if self.link:
values.append(["Symlink", "\n".join(self.link)])
if self.tagged:
values.append(["Configure", "\n".join(self.tagged)])

if not values:
return "No file attached to this entity."

return tabulate(values, headers=["Strategy", "Files"], tablefmt="grid")


class TaggedFilesHierarchy:
"""The TaggedFilesHierarchy represents a directory
Expand Down
16 changes: 16 additions & 0 deletions smartsim/entity/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,22 @@
to_configure = init_default([], to_configure, (list, str))
self.files = EntityFiles(to_configure, to_copy, to_symlink)

@property
def attached_files_table(self) -> str:
"""Return a list of attached files as a plain text table

:returns: String version of table
:rtype: str
"""
if not self.files:
return "No file attached to this model."
return str(self.files)

def print_attached_files(self) -> None:
"""Print a table of the attached files on std out
"""
print(self.attached_files_table)

Check warning on line 182 in smartsim/entity/model.py

View check run for this annotation

Codecov / codecov/patch

smartsim/entity/model.py#L182

Added line #L182 was not covered by tests

def colocate_db(self, *args: t.Any, **kwargs: t.Any) -> None:
"""An alias for ``Model.colocate_db_tcp``"""
warnings.warn(
Expand Down
1 change: 1 addition & 0 deletions tests/test_configs/to_copy_dir/mock.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
File mockup.
1 change: 1 addition & 0 deletions tests/test_configs/to_symlink_dir/mock2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
File mockup two.
89 changes: 86 additions & 3 deletions tests/test_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
from smartsim._core.generation import Generator
from smartsim.database import Orchestrator
from smartsim.settings import RunSettings
from tabulate import tabulate

from smartsim.settings import SbatchSettings

rs = RunSettings("python", exe_args="sleep.py")

Expand Down Expand Up @@ -108,7 +111,6 @@ def test_ensemble_overwrite_error(fileutils):


def test_full_exp(fileutils, wlmutils):

test_dir = fileutils.make_test_dir()
exp = Experiment("gen-test", test_dir, launcher="local")

Expand Down Expand Up @@ -148,7 +150,7 @@ def test_dir_files(fileutils):
params = {"THERMO": [10, 20, 30], "STEPS": [10, 20, 30]}
ensemble = exp.create_ensemble("dir_test", params=params, run_settings=rs)
conf_dir = fileutils.get_test_dir_path("test_dir")
ensemble.attach_generator_files(to_copy=conf_dir)
ensemble.attach_generator_files(to_configure=conf_dir)

exp.generate(ensemble)

Expand All @@ -160,6 +162,87 @@ def test_dir_files(fileutils):
assert osp.isfile(osp.join(model_path, "test.py"))


def test_print_files(fileutils, capsys):
"""Test the stdout print of files attached to an ensemble"""

test_dir = fileutils.make_test_dir()
exp = Experiment("print-attached-files-test", test_dir, launcher="local")

ensemble = exp.create_ensemble("dir_test", replicas=1, run_settings=rs)
ensemble.entities = []

ensemble.print_attached_files()
captured = capsys.readouterr()
assert captured.out == "The ensemble is empty, no files to show.\n"

params = {"THERMO": [10, 20], "STEPS": [20, 30]}
ensemble = exp.create_ensemble("dir_test", params=params, run_settings=rs)
gen_dir = fileutils.get_test_dir_path("test_dir")
symlink_dir = fileutils.get_test_dir_path("to_symlink_dir")
copy_dir = fileutils.get_test_dir_path("to_copy_dir")

ensemble.print_attached_files()
captured = capsys.readouterr()
expected_out = (
tabulate(
[
[model.name, "No file attached to this model."]
for model in ensemble.models
],
headers=["Model name", "Files"],
tablefmt="grid",
)
+ "\n"
)

assert captured.out == expected_out

ensemble.attach_generator_files()
ensemble.print_attached_files()
captured = capsys.readouterr()
expected_out = (
tabulate(
[
[model.name, "No file attached to this entity."]
for model in ensemble.models
],
headers=["Model name", "Files"],
tablefmt="grid",
)
+ "\n"
)
assert captured.out == expected_out

ensemble.attach_generator_files(
to_configure=[gen_dir, copy_dir], to_copy=copy_dir, to_symlink=symlink_dir
)

expected_out = tabulate(
[
["Copy", copy_dir],
["Symlink", symlink_dir],
["Configure", f"{gen_dir}\n{copy_dir}"],
],
headers=["Strategy", "Files"],
tablefmt="grid",
)

assert all(str(model.files) == expected_out for model in ensemble.models)

expected_out_multi = (
tabulate(
[[model.name, expected_out] for model in ensemble.models],
headers=["Model name", "Files"],
tablefmt="grid",
)
+ "\n"
)
ensemble.print_attached_files()

captured = capsys.readouterr()
assert captured.out == expected_out_multi


def test_multiple_tags(fileutils):
"""Test substitution of multiple tagged parameters on same line"""
test_dir = fileutils.make_test_dir()
Expand Down Expand Up @@ -198,7 +281,7 @@ def test_config_dir(fileutils):
gen.generate_experiment(ensemble)

assert osp.isdir(osp.join(test_dir, "test"))
# assert False

def _check_generated(test_num, param_0, param_1):
conf_test_dir = osp.join(test_dir, "test", f"test_{test_num}")
assert osp.isdir(conf_test_dir)
Expand Down
Loading