jobflow 0.1.9__py3-none-any.whl → 0.1.11__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
jobflow/core/flow.py CHANGED
@@ -140,7 +140,7 @@ class Flow(MSONable):
140
140
  self.uuid = uuid
141
141
  self.hosts = hosts or []
142
142
 
143
- self._jobs: tuple[Flow | Job, ...] = tuple()
143
+ self._jobs: tuple[Flow | Job, ...] = ()
144
144
  self.add_jobs(jobs)
145
145
  self.output = output
146
146
 
@@ -173,7 +173,8 @@ class Flow(MSONable):
173
173
  """
174
174
  Set the output of the Flow.
175
175
 
176
- The output should be compatible with the list of Jobs/Flows contained in the Flow.
176
+ The output should be compatible with the list of Jobs/Flows contained in the
177
+ Flow.
177
178
 
178
179
  Parameters
179
180
  ----------
@@ -406,8 +407,9 @@ class Flow(MSONable):
406
407
  update
407
408
  The updates to apply.
408
409
  name_filter
409
- A filter for the Maker name. Only Makers with a matching name will be updated.
410
- Includes partial matches, e.g. "ad" will match a Maker with the name "adder".
410
+ A filter for the Maker name. Only Makers with a matching name will be
411
+ updated. Includes partial matches, e.g. "ad" will match a Maker with the
412
+ name "adder".
411
413
  class_filter
412
414
  A filter for the maker class. Only Makers with a matching class will be
413
415
  updated. Note the class filter will match any subclasses.
@@ -533,7 +535,8 @@ class Flow(MSONable):
533
535
  Use the dict mod language to apply updates. See :obj:`.DictMods` for more
534
536
  details.
535
537
  dynamic
536
- The updates will be propagated to Jobs/Flows dynamically generated at runtime.
538
+ The updates will be propagated to Jobs/Flows dynamically generated at
539
+ runtime.
537
540
 
538
541
  Examples
539
542
  --------
@@ -587,7 +590,8 @@ class Flow(MSONable):
587
590
  Which attributes of the job config to set. Can be specified as one or more
588
591
  attributes specified by their name.
589
592
  dynamic
590
- The updates will be propagated to Jobs/Flows dynamically generated at runtime.
593
+ The updates will be propagated to Jobs/Flows dynamically generated at
594
+ runtime.
591
595
 
592
596
  Examples
593
597
  --------
@@ -678,7 +682,7 @@ class Flow(MSONable):
678
682
  jobs = [jobs]
679
683
 
680
684
  job_ids = set(self.all_uuids)
681
- hosts = [self.uuid] + self.hosts
685
+ hosts = [self.uuid, *self.hosts]
682
686
  for job in jobs:
683
687
  if job.host is not None and job.host != self.uuid:
684
688
  raise ValueError(
jobflow/core/job.py CHANGED
@@ -49,8 +49,8 @@ class JobConfig(MSONable):
49
49
  response_manager_config
50
50
  The custom configuration to pass to a detour, addition, or replacement job.
51
51
  Using this kwarg will automatically take precedence over the behavior of
52
- ``pass_manager_config`` such that a different configuration than ``manger_config``
53
- can be passed to downstream jobs.
52
+ ``pass_manager_config`` such that a different configuration than
53
+ ``manger_config`` can be passed to downstream jobs.
54
54
 
55
55
  Returns
56
56
  -------
@@ -116,9 +116,9 @@ def job(method: Callable | None = None, **job_kwargs):
116
116
  OutputReference('abeb6f48-9b34-4698-ab69-e4dc2127ebe9')
117
117
 
118
118
  .. Note::
119
- Because the task has not yet been run, the output value is :obj:`OutputReference`
120
- object. References are automatically converted to their computed values
121
- (resolved) when the task runs.
119
+ Because the task has not yet been run, the output value is an
120
+ :obj:`OutputReference` object. References are automatically converted to their
121
+ computed values (resolved) when the task runs.
122
122
 
123
123
  If a dictionary of values is returned, the values can be indexed in the usual
124
124
  way.
@@ -251,10 +251,11 @@ class Job(MSONable):
251
251
  The config setting for the job.
252
252
  hosts
253
253
  The list of UUIDs of the hosts containing the job. The object identified by one
254
- UUID of the list should be contained in objects identified by its subsequent elements.
254
+ UUID of the list should be contained in objects identified by its subsequent
255
+ elements.
255
256
  metadata_updates
256
- A list of updates for the metadata that will be applied to any Flow/Job generated
257
- by the job.
257
+ A list of updates for the metadata that will be applied to any Flow/Job
258
+ generated by the job.
258
259
  config_updates
259
260
  A list of updates for the config that will be applied to any Flow/Job generated
260
261
  by the job.
@@ -323,7 +324,7 @@ class Job(MSONable):
323
324
 
324
325
  from jobflow.utils.find import contains_flow_or_job
325
326
 
326
- function_args = tuple() if function_args is None else function_args
327
+ function_args = () if function_args is None else function_args
327
328
  function_kwargs = {} if function_kwargs is None else function_kwargs
328
329
  uuid = suuid() if uuid is None else uuid
329
330
  metadata = {} if metadata is None else metadata
@@ -584,12 +585,14 @@ class Job(MSONable):
584
585
  pass_manager_config(response.replace, passed_config)
585
586
 
586
587
  try:
587
- output = jsanitize(response.output, strict=True, enum_values=True)
588
- except AttributeError:
588
+ output = jsanitize(
589
+ response.output, strict=True, enum_values=True, allow_bson=True
590
+ )
591
+ except AttributeError as err:
589
592
  raise RuntimeError(
590
593
  "Job output contained an object that is not MSONable and therefore "
591
594
  "could not be serialized."
592
- )
595
+ ) from err
593
596
 
594
597
  save = {k: "output" if v is True else v for k, v in self._kwargs.items()}
595
598
  data = {
@@ -730,8 +733,9 @@ class Job(MSONable):
730
733
  update
731
734
  The updates to apply.
732
735
  name_filter
733
- A filter for the Maker name. Only Makers with a matching name will be updated.
734
- Includes partial matches, e.g. "ad" will match a Maker with the name "adder".
736
+ A filter for the Maker name. Only Makers with a matching name will be
737
+ updated. Includes partial matches, e.g. "ad" will match a Maker with the
738
+ name "adder".
735
739
  class_filter
736
740
  A filter for the maker class. Only Makers with a matching class will be
737
741
  updated. Note the class filter will match any subclasses.
@@ -802,7 +806,7 @@ class Job(MSONable):
802
806
  nested=nested,
803
807
  dict_mod=dict_mod,
804
808
  )
805
- setattr(self, "function", getattr(maker, self.function.__name__))
809
+ self.function = getattr(maker, self.function.__name__)
806
810
  elif nested:
807
811
  # also look for makers in job args and kwargs
808
812
  new_args = []
@@ -874,12 +878,13 @@ class Job(MSONable):
874
878
  Use the dict mod language to apply updates. See :obj:`.DictMods` for more
875
879
  details.
876
880
  dynamic
877
- The updates will be propagated to Jobs/Flows dynamically generated at runtime.
881
+ The updates will be propagated to Jobs/Flows dynamically generated at
882
+ runtime.
878
883
 
879
884
  Examples
880
885
  --------
881
- Consider a simple job that makes use of a :obj:`Maker` to generate additional jobs
882
- at runtime (see :obj:`Response` options for more details):
886
+ Consider a simple job that makes use of a :obj:`Maker` to generate additional
887
+ jobs at runtime (see :obj:`Response` options for more details):
883
888
 
884
889
  >>> @job
885
890
  ... def use_maker(maker):
@@ -902,12 +907,12 @@ class Job(MSONable):
902
907
  from jobflow.utils.dict_mods import apply_mod
903
908
 
904
909
  if dynamic:
905
- dict_input = dict(
906
- update=update,
907
- name_filter=name_filter,
908
- function_filter=function_filter,
909
- dict_mod=dict_mod,
910
- )
910
+ dict_input = {
911
+ "update": update,
912
+ "name_filter": name_filter,
913
+ "function_filter": function_filter,
914
+ "dict_mod": dict_mod,
915
+ }
911
916
  self.metadata_updates.append(dict_input)
912
917
 
913
918
  # unwrap the functions in case the job is a decorated one
@@ -957,7 +962,8 @@ class Job(MSONable):
957
962
  Which attributes of the job config to set. Can be specified as one or more
958
963
  attributes specified by their name.
959
964
  dynamic
960
- The updates will be propagated to Jobs/Flows dynamically generated at runtime.
965
+ The updates will be propagated to Jobs/Flows dynamically generated at
966
+ runtime.
961
967
 
962
968
  Examples
963
969
  --------
@@ -976,9 +982,9 @@ class Job(MSONable):
976
982
  ... )
977
983
  >>> add_job.update_config(new_config)
978
984
 
979
- To only update specific attributes, the ``attributes`` argument can be specified.
980
- For example, the following will only update the "manager_config" attribute of the
981
- job config.
985
+ To only update specific attributes, the ``attributes`` argument can be
986
+ specified. For example, the following will only update the "manager_config"
987
+ attribute of the job config.
982
988
 
983
989
  >>> add_job.update_config(new_config, attributes="manager_config")
984
990
 
@@ -1010,12 +1016,12 @@ class Job(MSONable):
1010
1016
  only be set for the `test_job` and not for the generated Jobs.
1011
1017
  """
1012
1018
  if dynamic:
1013
- dict_input = dict(
1014
- config=config,
1015
- name_filter=name_filter,
1016
- function_filter=function_filter,
1017
- attributes=attributes,
1018
- )
1019
+ dict_input = {
1020
+ "config": config,
1021
+ "name_filter": name_filter,
1022
+ "function_filter": function_filter,
1023
+ "attributes": attributes,
1024
+ }
1019
1025
  self.config_updates.append(dict_input)
1020
1026
 
1021
1027
  # unwrap the functions in case the job is a decorated one
@@ -1033,15 +1039,15 @@ class Job(MSONable):
1033
1039
 
1034
1040
  # if we get to here then we pass all the filters
1035
1041
  if isinstance(config, dict):
1036
- # convert dict specification to a JobConfig but set the attributes accordingly
1042
+ # convert dict specification to a JobConfig but set the attributes
1037
1043
  if attributes is None:
1038
1044
  attributes = list(config.keys())
1039
1045
 
1040
1046
  attributes = [attributes] if isinstance(attributes, str) else attributes
1041
1047
  if not set(attributes).issubset(set(config.keys())):
1042
1048
  raise ValueError(
1043
- "Specified attributes include a key that is not present in the config"
1044
- " dictionary."
1049
+ "Specified attributes include a key that is not present in the "
1050
+ "config dictionary."
1045
1051
  )
1046
1052
  config = JobConfig(**config)
1047
1053
 
@@ -1098,8 +1104,15 @@ class Job(MSONable):
1098
1104
  self.hosts.extend(hosts_uuids)
1099
1105
 
1100
1106
 
1107
+ # For type checking, the Response output type can be specified
1108
+ # in a type hint via this type variable.
1109
+ # For example, a signature `-> Response[int]` would require
1110
+ # that the Response.output is an int.
1111
+ T = typing.TypeVar("T")
1112
+
1113
+
1101
1114
  @dataclass
1102
- class Response:
1115
+ class Response(typing.Generic[T]):
1103
1116
  """
1104
1117
  The :obj:`Response` contains the output, detours, and stop commands of a job.
1105
1118
 
@@ -1121,7 +1134,7 @@ class Response:
1121
1134
  Stop executing all remaining jobs.
1122
1135
  """
1123
1136
 
1124
- output: Any | None = None
1137
+ output: T | None = None
1125
1138
  detour: jobflow.Flow | Job | list[Job] | list[jobflow.Flow] | None = None
1126
1139
  addition: jobflow.Flow | Job | list[Job] | list[jobflow.Flow] | None = None
1127
1140
  replace: jobflow.Flow | Job | list[Job] | list[jobflow.Flow] | None = None
jobflow/core/maker.py CHANGED
@@ -149,8 +149,9 @@ class Maker(MSONable):
149
149
  update
150
150
  The updates to apply.
151
151
  name_filter
152
- A filter for the Maker name. Only Makers with a matching name will be updated.
153
- Includes partial matches, e.g. "ad" will match a Maker with the name "adder".
152
+ A filter for the Maker name. Only Makers with a matching name will be
153
+ updated. Includes partial matches, e.g. "ad" will match a Maker with the
154
+ name "adder".
154
155
  class_filter
155
156
  A filter for the maker class. Only Makers with a matching class will be
156
157
  updated. Note the class filter will match any subclasses.
@@ -232,7 +233,7 @@ class Maker(MSONable):
232
233
 
233
234
  def recursive_call(
234
235
  obj: Maker,
235
- func: Callable[[Maker], Any],
236
+ func: Callable[[Maker], Maker],
236
237
  name_filter: str | None = None,
237
238
  class_filter: type[Maker] | None = None,
238
239
  nested: bool = True,
@@ -281,13 +282,11 @@ def recursive_call(
281
282
  # 2. Regenerate the classes and check if they are a Maker
282
283
  # 3. Call the functions on the deepest classes first
283
284
  # 4. Call the function or update on the deepest classes and move up the tree
284
- # 5. Finally replace the call/update the object itself
285
+ # 5. Finally, replace the call/update the object itself
285
286
 
286
287
  # find all classes in the serialized maker kwargs
287
- if nested:
288
- locations = find_key(d, "@class", nested=True)
289
- else:
290
- locations = [[]] # will only look at the top level if nested=False
288
+ # will only look at the top level if nested=False
289
+ locations = find_key(d, "@class", nested=True) if nested else [[]]
291
290
 
292
291
  for location in sorted(
293
292
  locations, key=len, reverse=True
@@ -298,7 +297,7 @@ def recursive_call(
298
297
  if _filter(nested_class):
299
298
  # either update or call the function on the nested Maker
300
299
  modified_class = func(nested_class)
301
- if not isinstance(modified_class, Maker): # pragma: no cover
300
+ if not isinstance(modified_class, Maker):
302
301
  raise ValueError(
303
302
  "Function must return a Maker object. "
304
303
  f"Got {type(modified_class)} instead."
jobflow/core/reference.py CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import contextlib
5
6
  import typing
6
7
  from typing import Any, Sequence
7
8
 
@@ -93,7 +94,7 @@ class OutputReference(MSONable):
93
94
  def __init__(
94
95
  self,
95
96
  uuid: str,
96
- attributes: tuple[tuple[str, Any], ...] = tuple(),
97
+ attributes: tuple[tuple[str, Any], ...] = (),
97
98
  output_schema: type[BaseModel] | None = None,
98
99
  ):
99
100
  super().__init__()
@@ -157,12 +158,10 @@ class OutputReference(MSONable):
157
158
  index = None if result is None else result["index"]
158
159
 
159
160
  if index is not None and index not in cache[self.uuid]:
160
- try:
161
+ with contextlib.suppress(ValueError):
161
162
  cache[self.uuid][index] = store.get_output(
162
163
  self.uuid, which="last", load=True, on_missing=on_missing
163
164
  )
164
- except ValueError:
165
- pass
166
165
 
167
166
  if on_missing == OnMissing.ERROR and index not in cache[self.uuid]:
168
167
  istr = f" ({index})" if index is not None else ""
@@ -183,12 +182,8 @@ class OutputReference(MSONable):
183
182
  cache[self.uuid][index] = data
184
183
 
185
184
  for attr_type, attr in self.attributes:
186
- if attr_type == "i":
187
- # index
188
- data = data[attr]
189
- else:
190
- # attribute access
191
- data = getattr(data, attr)
185
+ # i means index else use attribute access
186
+ data = data[attr] if attr_type == "i" else getattr(data, attr)
192
187
 
193
188
  return data
194
189
 
@@ -226,7 +221,7 @@ class OutputReference(MSONable):
226
221
  _, subschema = validate_schema_access(self.output_schema, item)
227
222
 
228
223
  return OutputReference(
229
- self.uuid, self.attributes + (("i", item),), output_schema=subschema
224
+ self.uuid, (*self.attributes, ("i", item)), output_schema=subschema
230
225
  )
231
226
 
232
227
  def __getattr__(self, item) -> OutputReference:
@@ -242,7 +237,7 @@ class OutputReference(MSONable):
242
237
  _, subschema = validate_schema_access(self.output_schema, item)
243
238
 
244
239
  return OutputReference(
245
- self.uuid, self.attributes + (("a", item),), output_schema=subschema
240
+ self.uuid, (*self.attributes, ("a", item)), output_schema=subschema
246
241
  )
247
242
 
248
243
  def __setattr__(self, attr, val):
@@ -390,13 +385,13 @@ def find_and_get_references(arg: Any) -> tuple[OutputReference, ...]:
390
385
 
391
386
  if isinstance(arg, OutputReference):
392
387
  # if the argument is a reference then stop there
393
- return tuple([arg])
388
+ return (arg,)
394
389
 
395
390
  elif isinstance(arg, (float, int, str, bool)):
396
391
  # argument is a primitive, we won't find a reference here
397
- return tuple()
392
+ return ()
398
393
 
399
- arg = jsanitize(arg, strict=True, enum_values=True)
394
+ arg = jsanitize(arg, strict=True, enum_values=True, allow_bson=True)
400
395
 
401
396
  # recursively find any reference classes
402
397
  locations = find_key_value(arg, "@class", "OutputReference")
@@ -453,7 +448,7 @@ def find_and_resolve_references(
453
448
  return arg
454
449
 
455
450
  # serialize the argument to a dictionary
456
- encoded_arg = jsanitize(arg, strict=True, enum_values=True)
451
+ encoded_arg = jsanitize(arg, strict=True, enum_values=True, allow_bson=True)
457
452
 
458
453
  # recursively find any reference classes
459
454
  locations = find_key_value(encoded_arg, "@class", "OutputReference")
jobflow/core/state.py CHANGED
@@ -24,10 +24,13 @@ __all__ = ["CURRENT_JOB"]
24
24
 
25
25
  @singleton
26
26
  class State:
27
+ """State of the current job and store."""
28
+
27
29
  job: jobflow.Job | None = None
28
30
  store: jobflow.JobStore | None = None
29
31
 
30
32
  def reset(self):
33
+ """Reset the current state."""
31
34
  self.job = None
32
35
  self.store = None
33
36
 
jobflow/core/store.py CHANGED
@@ -210,7 +210,7 @@ class JobStore(Store):
210
210
  properties=["blob_uuid", "data"],
211
211
  )
212
212
  object_map = {o["blob_uuid"]: o["data"] for o in objects}
213
- inserts = {tuple(l): object_map[o] for o, l in object_info.items()}
213
+ inserts = {tuple(v): object_map[k] for k, v in object_info.items()}
214
214
  to_insert.update(inserts)
215
215
 
216
216
  update_in_dictionary(doc, to_insert)
@@ -603,7 +603,7 @@ class JobStore(Store):
603
603
  return cls.from_dict_spec(store_info, **kwargs)
604
604
 
605
605
  @classmethod
606
- def from_dict_spec(cls: Type[T], spec: dict, **kwargs) -> T:
606
+ def from_dict_spec(cls: type[T], spec: dict, **kwargs) -> T:
607
607
  """
608
608
  Create an JobStore from a dict specification.
609
609
 
@@ -737,7 +737,7 @@ def _filter_blobs(
737
737
  from collections import defaultdict
738
738
 
739
739
  def _group_blobs(infos, locs):
740
- grouped = defaultdict(lambda: (list(), list()))
740
+ grouped = defaultdict(lambda: ([], []))
741
741
  for info, loc in zip(infos, locs):
742
742
  grouped[info["store"]][0].append(info)
743
743
  grouped[info["store"]][1].append(loc)
@@ -749,7 +749,7 @@ def _filter_blobs(
749
749
 
750
750
  new_blobs = []
751
751
  new_locations = []
752
- for store_name, store_load in load.items():
752
+ for _store_name, store_load in load.items():
753
753
  for blob, location in zip(blob_infos, locations):
754
754
  if store_load is True:
755
755
  new_blobs.append(blob)
@@ -763,10 +763,7 @@ def _filter_blobs(
763
763
  isinstance(ltype, tuple)
764
764
  and blob.get("@class", None) == ltype[1]
765
765
  and blob.get("@module", None) == ltype[0]
766
- ):
767
- new_blobs.append(blob)
768
- new_locations.append(location)
769
- elif location[-1] == ltype:
766
+ ) or location[-1] == ltype:
770
767
  new_blobs.append(blob)
771
768
  new_locations.append(location)
772
769
 
jobflow/managers/local.py CHANGED
@@ -147,7 +147,7 @@ def run_locally(
147
147
  if response is False:
148
148
  return False
149
149
 
150
- return True if response is not None else False
150
+ return response is not None
151
151
 
152
152
  logger.info("Started executing jobs locally")
153
153
  finished_successfully = _run(flow)
@@ -66,7 +66,7 @@ class DictMods:
66
66
  @staticmethod
67
67
  def unset(input_dict, settings):
68
68
  """Unset a value."""
69
- for k in settings.keys():
69
+ for k in settings:
70
70
  (d, key) = _get_nested_dict(input_dict, k)
71
71
  del d[key]
72
72
 
jobflow/utils/find.py CHANGED
@@ -88,18 +88,18 @@ def find_key(
88
88
 
89
89
  if key in obj:
90
90
  if include_end:
91
- found_items.add(path + (key,))
91
+ found_items.add((*path, key))
92
92
  else:
93
93
  found_items.add(path)
94
94
  found = True
95
95
 
96
96
  if not found or nested:
97
97
  for k, v in obj.items():
98
- _lookup(v, path + (k,))
98
+ _lookup(v, (*path, k))
99
99
 
100
100
  elif isinstance(obj, (list, tuple)):
101
101
  for i, v in enumerate(obj):
102
- _lookup(v, path + (i,))
102
+ _lookup(v, (*path, i))
103
103
 
104
104
  _lookup(d)
105
105
  return [list(path) for path in found_items]
@@ -146,11 +146,11 @@ def find_key_value(
146
146
  found_items.add(path)
147
147
 
148
148
  for k, v in obj.items():
149
- _lookup(v, path + (k,))
149
+ _lookup(v, (*path, k))
150
150
 
151
151
  elif isinstance(obj, (list, tuple)):
152
152
  for i, v in enumerate(obj):
153
- _lookup(v, path + (i,))
153
+ _lookup(v, (*path, i))
154
154
 
155
155
  _lookup(d)
156
156
  return tuple(list(path) for path in found_items)
jobflow/utils/graph.py CHANGED
@@ -85,7 +85,7 @@ def draw_graph(
85
85
  if layout_function is None:
86
86
  try:
87
87
  pos = nx.nx_pydot.graphviz_layout(graph, prog="dot")
88
- except (ImportError, ModuleNotFoundError, FileNotFoundError):
88
+ except (ImportError, FileNotFoundError):
89
89
  # graphviz not installed
90
90
  pos = nx.planar_layout(graph)
91
91
  else:
@@ -1,12 +1,14 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jobflow
3
- Version: 0.1.9
4
- Summary: jobflow is library for writing computational workflows
5
- Home-page: https://materialsproject.github.io/jobflow
6
- Author: Alex Ganose
7
- Author-email: alexganose@googlemail.com
3
+ Version: 0.1.11
4
+ Summary: jobflow is a library for writing computational workflows
5
+ Author-email: Alex Ganose <alexganose@gmail.com>
8
6
  License: modified BSD
9
- Platform: UNKNOWN
7
+ Project-URL: homepage, https://materialsproject.github.io/jobflow/
8
+ Project-URL: repository, https://github.com/materialsproject/jobflow
9
+ Project-URL: documentation, https://materialsproject.github.io/jobflow/
10
+ Project-URL: changelog, https://github.com/materialsproject/jobflow/blob/main/CHANGELOG.md
11
+ Keywords: high-throughput,workflow
10
12
  Classifier: Programming Language :: Python :: 3
11
13
  Classifier: Programming Language :: Python :: 3.8
12
14
  Classifier: Programming Language :: Python :: 3.9
@@ -22,7 +24,6 @@ Classifier: Topic :: Scientific/Engineering
22
24
  Requires-Python: >=3.8
23
25
  Description-Content-Type: text/markdown
24
26
  License-File: LICENSE
25
- Requires-Dist: setuptools
26
27
  Requires-Dist: monty (>=2021.5.9)
27
28
  Requires-Dist: pydash
28
29
  Requires-Dist: networkx
@@ -32,34 +33,41 @@ Requires-Dist: PyYAML
32
33
  Provides-Extra: dev
33
34
  Requires-Dist: pre-commit (>=2.12.1) ; extra == 'dev'
34
35
  Provides-Extra: docs
35
- Requires-Dist: sphinx (==5.2.1) ; extra == 'docs'
36
- Requires-Dist: furo (==2022.9.15) ; extra == 'docs'
37
- Requires-Dist: m2r2 (==0.3.3) ; extra == 'docs'
38
- Requires-Dist: ipython (==8.5.0) ; extra == 'docs'
39
- Requires-Dist: nbsphinx (==0.8.9) ; extra == 'docs'
40
- Requires-Dist: nbsphinx-link (==1.3.0) ; extra == 'docs'
41
- Requires-Dist: FireWorks (==2.0.3) ; extra == 'docs'
42
- Requires-Dist: autodoc-pydantic (==1.7.2) ; extra == 'docs'
36
+ Requires-Dist: sphinx (==6.1.3) ; extra == 'docs'
37
+ Requires-Dist: furo (==2022.12.7) ; extra == 'docs'
38
+ Requires-Dist: myst-parser (==1.0.0) ; extra == 'docs'
39
+ Requires-Dist: ipython (==8.11.0) ; extra == 'docs'
40
+ Requires-Dist: nbsphinx (==0.9.0) ; extra == 'docs'
41
+ Requires-Dist: autodoc-pydantic (==1.8.0) ; extra == 'docs'
43
42
  Provides-Extra: fireworks
44
- Requires-Dist: fireworks ; extra == 'fireworks'
43
+ Requires-Dist: FireWorks ; extra == 'fireworks'
44
+ Provides-Extra: strict
45
+ Requires-Dist: monty (==2022.9.9) ; extra == 'strict'
46
+ Requires-Dist: networkx (==3.0) ; extra == 'strict'
47
+ Requires-Dist: pydash (==6.0.2) ; extra == 'strict'
48
+ Requires-Dist: maggma (==0.50.3) ; extra == 'strict'
49
+ Requires-Dist: pydantic (==1.10.6) ; extra == 'strict'
50
+ Requires-Dist: PyYAML (==6.0) ; extra == 'strict'
51
+ Requires-Dist: FireWorks (==2.0.3) ; extra == 'strict'
52
+ Requires-Dist: matplotlib (==3.7.1) ; extra == 'strict'
53
+ Requires-Dist: pydot (==1.4.2) ; extra == 'strict'
54
+ Requires-Dist: moto (==4.1.4) ; extra == 'strict'
45
55
  Provides-Extra: tests
46
- Requires-Dist: pytest (==7.1.3) ; extra == 'tests'
47
- Requires-Dist: pytest-cov (==3.0.0) ; extra == 'tests'
48
- Requires-Dist: FireWorks (==2.0.3) ; extra == 'tests'
49
- Requires-Dist: matplotlib (==3.6.0) ; extra == 'tests'
50
- Requires-Dist: pydot (==1.4.2) ; extra == 'tests'
51
- Requires-Dist: moto (==4.0.5) ; extra == 'tests'
56
+ Requires-Dist: pytest (==7.2.2) ; extra == 'tests'
57
+ Requires-Dist: pytest-cov (==4.0.0) ; extra == 'tests'
52
58
  Provides-Extra: vis
53
59
  Requires-Dist: matplotlib ; extra == 'vis'
54
60
  Requires-Dist: pydot ; extra == 'vis'
55
61
 
56
62
  # jobflow
57
63
 
58
- <a href="https://github.com/materialsproject/jobflow/actions?query=workflow%3Atesting"><img alt="code coverage" src="https://img.shields.io/github/workflow/status/materialsproject/jobflow/testing?label=tests"></a>
64
+ <a href="https://github.com/materialsproject/jobflow/actions?query=workflow%3Atesting"><img alt="code coverage" src="https://img.shields.io/github/actions/workflow/status/materialsproject/jobflow/testing.yml?branch=main&label=tests"></a>
59
65
  <a href="https://codecov.io/gh/materialsproject/jobflow/"><img alt="code coverage" src="https://img.shields.io/codecov/c/gh/materialsproject/jobflow/main"></a>
60
66
  <a href="https://pypi.org/project/jobflow"><img alt="pypi version" src="https://img.shields.io/pypi/v/jobflow?color=blue"></a>
61
67
  <img alt="supported python versions" src="https://img.shields.io/pypi/pyversions/jobflow">
62
68
 
69
+ [Documentation](https://materialsproject.github.io/jobflow/) | [PyPI](https://pypi.org/project/jobflow/) | [GitHub](https://github.com/materialsproject/jobflow)
70
+
63
71
  Jobflow is a free, open-source library for writing and executing workflows. Complex
64
72
  workflows can be defined using simple python functions and executed locally or on
65
73
  arbitrary computing resources using the [FireWorks][fireworks] workflow manager.
@@ -129,7 +137,7 @@ the jobs is determined automatically and can be visualised using the flow graph.
129
137
 
130
138
  ## Installation
131
139
 
132
- The jobflow is a Python 3.7+ library and can be installed using pip.
140
+ The jobflow is a Python 3.8+ library and can be installed using pip.
133
141
 
134
142
  ```bash
135
143
  pip install jobflow
@@ -182,5 +190,3 @@ Jobflow was designed by Alex Ganose, Anubhav Jain, Gian-Marco Rignanese, David W
182
190
  [dynamic-flows]: https://materialsproject.github.io/jobflow/tutorials/5-dynamic-flows.html
183
191
  [jobflow-database]: https://materialsproject.github.io/jobflow/tutorials/6-jobflow-database.html
184
192
  [jobflow-fireworks]: https://materialsproject.github.io/jobflow/tutorials/7-fireworks.html
185
-
186
-
@@ -0,0 +1,26 @@
1
+ jobflow/__init__.py,sha256=l7o10BaqEQWw5aZziWRg40PsIAgQ4lrlluXs9hIv2mg,570
2
+ jobflow/_version.py,sha256=ERuIgO0lzbMrVMSXNAE55GxFc5JHDdf1CW7GtoXJ67Q,206
3
+ jobflow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ jobflow/settings.py,sha256=JHyTq9AOzMjSN5ohpLeooMLM0ddO2nPMuHuOyH62X6E,4908
5
+ jobflow/core/__init__.py,sha256=3sx5t1Gysejc4c_fPrhvCjPUg0p_384Zko8ms2c_NnY,98
6
+ jobflow/core/flow.py,sha256=b2XRc8Qvf2c5eXOyi2MP0_NEb6nKuN0QuOnyiGypvSI,25108
7
+ jobflow/core/job.py,sha256=TVbx5XRQx1axGFwUZbRODbmZoVLdbM95xAaAdpFIGbM,45491
8
+ jobflow/core/maker.py,sha256=4y76hHopYbV5HjjhHZRkRpdv8yCOuxfIdSXG_hLcY_0,11234
9
+ jobflow/core/reference.py,sha256=xb9AtRyZ11AkLNQCy4OlZ1xf6O84lIybrVesTrNsVCE,16401
10
+ jobflow/core/state.py,sha256=5LWKTAiYEkUWuFEZNeLtRZ0KCR3qMwZYJRN03zOM4X0,760
11
+ jobflow/core/store.py,sha256=YKS06FJqK4wx1F8YuJWnXC51yTaL5zD2ZqFFN9U8VSQ,26383
12
+ jobflow/managers/__init__.py,sha256=KkA5cVDe2os2_2aTa8eiB9SnkGLZNybcci-Lo4tbaWM,55
13
+ jobflow/managers/fireworks.py,sha256=7O6g23fnr9VBTGAy8h9OR_P9D2KvuQ7-XYTi0O0sqB4,5941
14
+ jobflow/managers/local.py,sha256=z8Ae-a_rUKqnCLsBAM9UIz0xZfCT3AxUWTxJQEf4Er4,4372
15
+ jobflow/utils/__init__.py,sha256=meuvfuk05U594rx4YB6BoBnoQxBMjCA2hKX3TSfZsB8,328
16
+ jobflow/utils/dict_mods.py,sha256=bJmHB-JHtwBwEpWroO1YaOac_AvCItoQ6GBWlWdDMtk,6090
17
+ jobflow/utils/enum.py,sha256=mt8z0D2Nu2oQxZ1vXi6VTqorOMseRptSCjsgMNSvvOE,756
18
+ jobflow/utils/find.py,sha256=VRqdDAnx-RavNvdVJ7TVEfvnBIkKR2HhHyOy7lh1QC8,5556
19
+ jobflow/utils/graph.py,sha256=T7M5gOeAxK4CaAynepY11ysEp5Q6ccJ62ZJ4nCFZeVQ,4578
20
+ jobflow/utils/log.py,sha256=dNIOvhApCtW7z1OamLlUmg6TL4mDXOQ0yFQxD8AM0Lk,725
21
+ jobflow/utils/uuid.py,sha256=lVgo8e8gUB7HLSR0H_9uZH-OPkVBaOT39atAnNKYAaI,268
22
+ jobflow-0.1.11.dist-info/LICENSE,sha256=jUEiENfZNQZh9RE9ixtUWgVkLRD85ScZ6iv1WREf19w,2418
23
+ jobflow-0.1.11.dist-info/METADATA,sha256=P3zSomFDef_b3DmPltaNidz_NqBDK-nUr1QxsfLvXAE,8814
24
+ jobflow-0.1.11.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
25
+ jobflow-0.1.11.dist-info/top_level.txt,sha256=IanNooU88OupQPDrWnT0rbL3E27P2wEy7Jsfx9_j8zc,8
26
+ jobflow-0.1.11.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.37.1)
2
+ Generator: bdist_wheel (0.40.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,26 +0,0 @@
1
- jobflow/__init__.py,sha256=l7o10BaqEQWw5aZziWRg40PsIAgQ4lrlluXs9hIv2mg,570
2
- jobflow/_version.py,sha256=ERuIgO0lzbMrVMSXNAE55GxFc5JHDdf1CW7GtoXJ67Q,206
3
- jobflow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- jobflow/settings.py,sha256=JHyTq9AOzMjSN5ohpLeooMLM0ddO2nPMuHuOyH62X6E,4908
5
- jobflow/core/__init__.py,sha256=3sx5t1Gysejc4c_fPrhvCjPUg0p_384Zko8ms2c_NnY,98
6
- jobflow/core/flow.py,sha256=Wraue_5xCMC0ZFQ9Bsqqg6vCpyvTVKIxJ58qzv3WdU0,25069
7
- jobflow/core/job.py,sha256=SIkHr8UZ1wqvPPGoWXElixujBgPy9jDKWtlXvgtSZfo,45148
8
- jobflow/core/maker.py,sha256=g98e3uJeV5WH4vbJHM-03-idjfzywasP6x9UrbYRR-M,11270
9
- jobflow/core/reference.py,sha256=LwqlQ6oXMpMR22NWCEYHd9IBxAfXQgHGuTtyxPmJmEc,16444
10
- jobflow/core/state.py,sha256=wGgsk6Qv2CroW_r0nBSkgbAQpeBD-lzEMWDy0hCwCr0,674
11
- jobflow/core/store.py,sha256=l7PRf8nVixvO2GAwHrJSPkZe_jczjGylosFm-3TDQ4o,26515
12
- jobflow/managers/__init__.py,sha256=KkA5cVDe2os2_2aTa8eiB9SnkGLZNybcci-Lo4tbaWM,55
13
- jobflow/managers/fireworks.py,sha256=7O6g23fnr9VBTGAy8h9OR_P9D2KvuQ7-XYTi0O0sqB4,5941
14
- jobflow/managers/local.py,sha256=uc233Oq7k-2ZeNUIDxArqjBZs5C1MR6gZf4dKchet50,4391
15
- jobflow/utils/__init__.py,sha256=meuvfuk05U594rx4YB6BoBnoQxBMjCA2hKX3TSfZsB8,328
16
- jobflow/utils/dict_mods.py,sha256=vJT89GF0pu_xXlIQRwlO9Vsgqgs_r0IteBP8_skREJM,6097
17
- jobflow/utils/enum.py,sha256=mt8z0D2Nu2oQxZ1vXi6VTqorOMseRptSCjsgMNSvvOE,756
18
- jobflow/utils/find.py,sha256=7U_Blhg7K0P43Gow5h5IZnolzTg5R5lDsR8D0hKc_IM,5561
19
- jobflow/utils/graph.py,sha256=asc4ANbNKeY27UMxhvGFO9LG2s8gdjUpSL9eU3NGo7o,4599
20
- jobflow/utils/log.py,sha256=dNIOvhApCtW7z1OamLlUmg6TL4mDXOQ0yFQxD8AM0Lk,725
21
- jobflow/utils/uuid.py,sha256=lVgo8e8gUB7HLSR0H_9uZH-OPkVBaOT39atAnNKYAaI,268
22
- jobflow-0.1.9.dist-info/LICENSE,sha256=jUEiENfZNQZh9RE9ixtUWgVkLRD85ScZ6iv1WREf19w,2418
23
- jobflow-0.1.9.dist-info/METADATA,sha256=65Uc3eR3XxHs0RghLhXUUP1sO5LcgzdhITrq6ZDFoZ0,8161
24
- jobflow-0.1.9.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
25
- jobflow-0.1.9.dist-info/top_level.txt,sha256=IanNooU88OupQPDrWnT0rbL3E27P2wEy7Jsfx9_j8zc,8
26
- jobflow-0.1.9.dist-info/RECORD,,