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

[patch] Introduce a flag for _not_ mangling the name of wrapped function jobs #1356

Merged
merged 11 commits into from
Mar 7, 2024
30 changes: 20 additions & 10 deletions pyiron_base/jobs/flex/pythonfunctioncontainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def __init__(self, project, job_name):
super().__init__(project, job_name)
self._function = None
self._executor_type = None
self._automatically_rename_on_save_using_input = True

@property
def python_function(self):
Expand All @@ -64,23 +65,32 @@ def __call__(self, *args, **kwargs):
def to_hdf(self, hdf=None, group_name=None):
super().to_hdf(hdf=hdf, group_name=group_name)
self.project_hdf5["function"] = np.void(cloudpickle.dumps(self._function))
self.project_hdf5["_automatically_rename_on_save_using_input"] = (
self._automatically_rename_on_save_using_input
)

def from_hdf(self, hdf=None, group_name=None):
super().from_hdf(hdf=hdf, group_name=group_name)
self._function = cloudpickle.loads(self.project_hdf5["function"])
self._automatically_rename_on_save_using_input = bool(
self.project_hdf5["_automatically_rename_on_save_using_input"]
)

def save(self):
job_name = self._function.__name__ + get_hash(
binary=cloudpickle.dumps(
{"fn": self._function, "kwargs": self.input.to_builtin()}
if self._automatically_rename_on_save_using_input:
job_name = self._function.__name__ + get_hash(
binary=cloudpickle.dumps(
{"fn": self._function, "kwargs": self.input.to_builtin()}
)
)
)
self.job_name = job_name
if job_name in self.project.list_nodes():
self.from_hdf()
self.status.finished = True
else:
super().save()

self.job_name = job_name

if self.job_name in self.project.list_nodes():
self.from_hdf()
self.status.finished = True
return # Without saving
super().save()

def run_static(self):
if (
Expand Down
50 changes: 49 additions & 1 deletion tests/flex/test_pythonfunctioncontainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ def test_with_executor(self):
self.assertIsNone(job.server.future.result())
self.assertTrue(job.server.future.done())

@unittest.skipIf(os.name == "nt", "Starting subprocesses on windows take a long time.")
@unittest.skipIf(
os.name == "nt", "Starting subprocesses on windows take a long time."
)
def test_terminate_job(self):
job = self.project.wrap_python_function(my_sleep_funct)
job.input["a"] = 5
Expand Down Expand Up @@ -100,3 +102,49 @@ def test_with_internal_executor(self):
job.run()
self.assertEqual(job.output["result"], [6, 8, 10, 12])
self.assertTrue(job.status.finished)

def test_name_mangling(self):
def make_a_simple_job():
job = self.project.wrap_python_function(my_function)
job.input["a"] = 1
job.input["b"] = 2
return job

job = make_a_simple_job()
self.assertEqual(
job.job_name,
my_function.__name__,
msg="Sanity check"
)
try:
job.save()
self.assertNotEqual(
job.job_name,
my_function.__name__,
msg="By default, we expect the wrapped job names to get mangled based "
"on their input so multiple calls to the wrap get unique names"
)
loaded = self.project.load(job.job_name)
self.assertTrue(
loaded._automatically_rename_on_save_using_input,
msg="The mangling preference should survive saving and loading"
)
finally:
job.remove()

job = make_a_simple_job()
job._automatically_rename_on_save_using_input = False
try:
job.save()
self.assertEqual(
job.job_name,
my_function.__name__,
msg="When requested, the job name should retain its original value"
)
loaded = self.project.load(job.job_name)
self.assertFalse(
loaded._automatically_rename_on_save_using_input,
msg="The mangling preference should survive saving and loading"
)
finally:
job.remove()
Loading