-
Notifications
You must be signed in to change notification settings - Fork 26
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
Add Flow.metadata
attribute and Flow.update_metadata
method
#679
Changes from 10 commits
b4b349d
afdbb1f
367836b
e38237d
9969640
c6a1732
dc23d2e
aa4a02f
1993511
9f16d51
b6786ca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -343,7 +343,6 @@ def __init__( | |
function_args = () if function_args is None else function_args | ||
function_kwargs = {} if function_kwargs is None else function_kwargs | ||
uuid = suid() if uuid is None else uuid | ||
metadata = {} if metadata is None else metadata | ||
config = JobConfig() if config is None else config | ||
|
||
# make a deep copy of the function (means makers do not share the same instance) | ||
|
@@ -354,7 +353,7 @@ def __init__( | |
self.uuid = uuid | ||
self.index = index | ||
self.name = name | ||
self.metadata = metadata | ||
self.metadata = metadata or {} | ||
self.config = config | ||
self.hosts = hosts or [] | ||
self.metadata_updates = metadata_updates or [] | ||
|
@@ -927,6 +926,7 @@ def update_metadata( | |
function_filter: Callable = None, | ||
dict_mod: bool = False, | ||
dynamic: bool = True, | ||
callback_filter: Callable[[jobflow.Flow | Job], bool] = lambda _: True, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @janosh: the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I didn't consider serialization. Sounds like something we need to add unit tests for. I'm guessing you can't literal_eval a callable safely? in which case not sure there's a solution other than removing the keyword. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or you issue an error when someone tries to serialize a callback_filter to explain that this feature is only compatible with create-and-run kind of workflows There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Serialisation shouldn't be a problem if the function is importable, e.g if it is defined in atomate2 or another package. Alternatively we could pickle it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The default There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
the intended use case is for
that might work. though we'd have to test cross-platform and cross-Python round-tripping. I've had cases where something pickled on Mac couldn't be unpickled on Linux (and likewise with Python 3.8 vs, say, 3.12) but |
||
): | ||
""" | ||
Update the metadata of the job. | ||
|
@@ -950,6 +950,9 @@ def update_metadata( | |
dynamic | ||
The updates will be propagated to Jobs/Flows dynamically generated at | ||
runtime. | ||
callback_filter | ||
A function that takes a Flow or Job instance and returns True if updates | ||
should be applied to that instance. Allows for custom filtering logic. | ||
|
||
Examples | ||
-------- | ||
|
@@ -968,11 +971,16 @@ def update_metadata( | |
will not only set the `example` metadata to the `test_job`, but also to all the | ||
new Jobs that will be generated at runtime by the ExampleMaker. | ||
|
||
`update_metadata` can be called multiple times with different `name_filter` or | ||
`function_filter` to control which Jobs will be updated. | ||
`update_metadata` can be called multiple times with different filters to control | ||
which Jobs will be updated. For example, using a callback filter: | ||
|
||
>>> test_job.update_metadata( | ||
... {"material_id": 42}, | ||
... callback_filter=lambda job: isinstance(job.maker, SomeMaker) | ||
... ) | ||
|
||
At variance, if `dynamic` is set to `False` the `example` metadata will only be | ||
added to the `test_job` and not to the generated Jobs. | ||
At variance, if `dynamic` is set to `False` the metadata will only be | ||
added to the filtered Jobs and not to any generated Jobs. | ||
""" | ||
from jobflow.utils.dict_mods import apply_mod | ||
|
||
|
@@ -982,14 +990,14 @@ def update_metadata( | |
"name_filter": name_filter, | ||
"function_filter": function_filter, | ||
"dict_mod": dict_mod, | ||
"callback_filter": callback_filter, | ||
} | ||
self.metadata_updates.append(dict_input) | ||
|
||
# unwrap the functions in case the job is a decorated one | ||
function_filter = getattr(function_filter, "__wrapped__", function_filter) | ||
function = getattr(self.function, "__wrapped__", self.function) | ||
|
||
# if function_filter is not None and function_filter != self.function: | ||
if function_filter is not None and function_filter != function: | ||
return | ||
|
||
|
@@ -998,6 +1006,9 @@ def update_metadata( | |
): | ||
return | ||
|
||
if callback_filter(self) is False: | ||
return | ||
|
||
# if we get to here then we pass all the filters | ||
if dict_mod: | ||
apply_mod(update, self.metadata) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please can you add docstrings for these options in the class docstring? E.g. see the corresponding docs for Job.