jobflow 0.1.17__py3-none-any.whl → 0.1.18__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
@@ -158,9 +158,8 @@ class Flow(MSONable):
158
158
  self, idx: int | slice, value: Flow | Job | Sequence[Flow | Job]
159
159
  ) -> None:
160
160
  """Set the job(s) or subflow(s) at the given index/slice."""
161
- if (
162
- not isinstance(value, (Flow, jobflow.Job, tuple, list))
163
- or isinstance(value, (tuple, list))
161
+ if not isinstance(value, (Flow, jobflow.Job, tuple, list)) or (
162
+ isinstance(value, (tuple, list))
164
163
  and not all(isinstance(v, (Flow, jobflow.Job)) for v in value)
165
164
  ):
166
165
  raise TypeError(
@@ -583,7 +582,7 @@ class Flow(MSONable):
583
582
  dict_mod=dict_mod,
584
583
  )
585
584
 
586
- def append_name(self, append_str: str, prepend: bool = False):
585
+ def append_name(self, append_str: str, prepend: bool = False, dynamic: bool = True):
587
586
  """
588
587
  Append a string to the name of the flow and all jobs contained in it.
589
588
 
@@ -600,7 +599,7 @@ class Flow(MSONable):
600
599
  self.name += append_str
601
600
 
602
601
  for job in self:
603
- job.append_name(append_str, prepend=prepend)
602
+ job.append_name(append_str, prepend=prepend, dynamic=dynamic)
604
603
 
605
604
  def update_metadata(
606
605
  self,
jobflow/core/job.py CHANGED
@@ -6,14 +6,17 @@ import logging
6
6
  import typing
7
7
  import warnings
8
8
  from dataclasses import dataclass, field
9
+ from typing import cast, overload
9
10
 
10
11
  from monty.json import MSONable, jsanitize
12
+ from typing_extensions import Self
11
13
 
12
14
  from jobflow.core.reference import OnMissing, OutputReference
13
15
  from jobflow.utils.uid import suid
14
16
 
15
17
  if typing.TYPE_CHECKING:
16
18
  from collections.abc import Hashable, Sequence
19
+ from pathlib import Path
17
20
  from typing import Any, Callable
18
21
 
19
22
  from networkx import DiGraph
@@ -65,7 +68,19 @@ class JobConfig(MSONable):
65
68
  response_manager_config: dict = field(default_factory=dict)
66
69
 
67
70
 
68
- def job(method: Callable = None, **job_kwargs):
71
+ @overload
72
+ def job(method: Callable = None) -> Callable[..., Job]:
73
+ pass
74
+
75
+
76
+ @overload
77
+ def job(method: Callable = None, **job_kwargs) -> Callable[..., Callable[..., Job]]:
78
+ pass
79
+
80
+
81
+ def job(
82
+ method: Callable = None, **job_kwargs
83
+ ) -> Callable[..., Job] | Callable[..., Callable[..., Job]]:
69
84
  """
70
85
  Wrap a function to produce a :obj:`Job`.
71
86
 
@@ -313,6 +328,7 @@ class Job(MSONable):
313
328
  hosts: list[str] = None,
314
329
  metadata_updates: list[dict[str, Any]] = None,
315
330
  config_updates: list[dict[str, Any]] = None,
331
+ name_updates: list[dict[str, Any]] = None,
316
332
  **kwargs,
317
333
  ):
318
334
  from copy import deepcopy
@@ -337,6 +353,7 @@ class Job(MSONable):
337
353
  self.config = config
338
354
  self.hosts = hosts or []
339
355
  self.metadata_updates = metadata_updates or []
356
+ self.name_updates = name_updates or []
340
357
  self.config_updates = config_updates or []
341
358
  self._kwargs = kwargs
342
359
 
@@ -526,7 +543,7 @@ class Job(MSONable):
526
543
  self.uuid = uuid
527
544
  self.output = self.output.set_uuid(uuid)
528
545
 
529
- def run(self, store: jobflow.JobStore) -> Response:
546
+ def run(self, store: jobflow.JobStore, job_dir: Path = None) -> Response:
530
547
  """
531
548
  Run the job.
532
549
 
@@ -581,7 +598,9 @@ class Job(MSONable):
581
598
  function = types.MethodType(function, bound)
582
599
 
583
600
  response = function(*self.function_args, **self.function_kwargs)
584
- response = Response.from_job_returns(response, self.output_schema)
601
+ response = Response.from_job_returns(
602
+ response, self.output_schema, job_dir=job_dir
603
+ )
585
604
 
586
605
  if response.replace is not None:
587
606
  response.replace = prepare_replace(response.replace, self)
@@ -604,6 +623,8 @@ class Job(MSONable):
604
623
  new_jobs.update_metadata(**metadata_update, dynamic=True)
605
624
  for config_update in self.config_updates:
606
625
  new_jobs.update_config(**config_update, dynamic=True)
626
+ for name_update in self.name_updates:
627
+ new_jobs.append_name(**name_update, dynamic=True)
607
628
 
608
629
  if self.config.response_manager_config:
609
630
  passed_config = self.config.response_manager_config
@@ -872,7 +893,7 @@ class Job(MSONable):
872
893
  dict_mod=dict_mod,
873
894
  )
874
895
 
875
- def append_name(self, append_str: str, prepend: bool = False):
896
+ def append_name(self, append_str: str, prepend: bool = False, dynamic: bool = True):
876
897
  """
877
898
  Append a string to the name of the job.
878
899
 
@@ -882,12 +903,18 @@ class Job(MSONable):
882
903
  A string to append.
883
904
  prepend
884
905
  Prepend the name rather than appending it.
906
+ dynamic
907
+ The updates will be propagated to Jobs/Flows dynamically generated at
908
+ runtime.
885
909
  """
886
910
  if prepend:
887
911
  self.name = append_str + self.name
888
912
  else:
889
913
  self.name += append_str
890
914
 
915
+ if dynamic:
916
+ self.name_updates.append({"append_str": append_str, "prepend": prepend})
917
+
891
918
  def update_metadata(
892
919
  self,
893
920
  update: dict[str, Any],
@@ -1134,8 +1161,8 @@ class Job(MSONable):
1134
1161
  prepend
1135
1162
  Insert the UUIDs at the beginning of the list rather than extending it.
1136
1163
  """
1137
- if not isinstance(hosts_uuids, (list, tuple)):
1138
- hosts_uuids = [hosts_uuids] # type: ignore
1164
+ if isinstance(hosts_uuids, str):
1165
+ hosts_uuids = [hosts_uuids]
1139
1166
  if prepend:
1140
1167
  self.hosts[0:0] = hosts_uuids
1141
1168
  else:
@@ -1170,6 +1197,8 @@ class Response(typing.Generic[T]):
1170
1197
  Stop any children of the current flow.
1171
1198
  stop_jobflow
1172
1199
  Stop executing all remaining jobs.
1200
+ job_dir
1201
+ The directory where the job was run.
1173
1202
  """
1174
1203
 
1175
1204
  output: T = None
@@ -1179,13 +1208,15 @@ class Response(typing.Generic[T]):
1179
1208
  stored_data: dict[Hashable, Any] = None
1180
1209
  stop_children: bool = False
1181
1210
  stop_jobflow: bool = False
1211
+ job_dir: str | Path = None
1182
1212
 
1183
1213
  @classmethod
1184
1214
  def from_job_returns(
1185
1215
  cls,
1186
1216
  job_returns: Any | None,
1187
1217
  output_schema: type[BaseModel] = None,
1188
- ) -> Response:
1218
+ job_dir: str | Path = None,
1219
+ ) -> Self:
1189
1220
  """
1190
1221
  Generate a :obj:`Response` from the outputs of a :obj:`Job`.
1191
1222
 
@@ -1199,6 +1230,8 @@ class Response(typing.Generic[T]):
1199
1230
  output_schema
1200
1231
  A pydantic model associated with the job. Used to enforce a schema for the
1201
1232
  outputs.
1233
+ job_dir
1234
+ The directory where the job was run.
1202
1235
 
1203
1236
  Raises
1204
1237
  ------
@@ -1215,17 +1248,18 @@ class Response(typing.Generic[T]):
1215
1248
  # only apply output schema if there is no replace.
1216
1249
  job_returns.output = apply_schema(job_returns.output, output_schema)
1217
1250
 
1218
- return job_returns
1251
+ job_returns.job_dir = job_dir
1252
+ return cast(Self, job_returns)
1219
1253
 
1220
1254
  if isinstance(job_returns, (list, tuple)):
1221
1255
  # check that a Response object is not given as one of many outputs
1222
- for r in job_returns:
1223
- if isinstance(r, Response):
1256
+ for resp in job_returns:
1257
+ if isinstance(resp, Response):
1224
1258
  raise ValueError(
1225
1259
  "Response cannot be returned in combination with other outputs."
1226
1260
  )
1227
1261
 
1228
- return cls(output=apply_schema(job_returns, output_schema))
1262
+ return cls(output=apply_schema(job_returns, output_schema), job_dir=job_dir)
1229
1263
 
1230
1264
 
1231
1265
  def apply_schema(output: Any, schema: type[BaseModel] | None):
jobflow/core/maker.py CHANGED
@@ -269,9 +269,7 @@ def recursive_call(
269
269
  return False
270
270
  if name_filter is not None and name_filter not in nested_obj.name:
271
271
  return False
272
- if class_filter is not None and not isinstance(nested_obj, class_filter):
273
- return False
274
- return True
272
+ return class_filter is None or isinstance(nested_obj, class_filter)
275
273
 
276
274
  d = obj.as_dict()
277
275
 
jobflow/core/reference.py CHANGED
@@ -82,7 +82,7 @@ class OutputReference(MSONable):
82
82
  OutputReference(1234, ['key'], [0], .value)
83
83
  """
84
84
 
85
- __slots__ = ("uuid", "attributes", "output_schema")
85
+ __slots__ = ("attributes", "output_schema", "uuid")
86
86
 
87
87
  def __init__(
88
88
  self,
jobflow/core/store.py CHANGED
@@ -17,6 +17,7 @@ if typing.TYPE_CHECKING:
17
17
  from typing import Any, Optional, Union
18
18
 
19
19
  from maggma.core import Sort
20
+ from typing_extensions import Self
20
21
 
21
22
  from jobflow.core.schemas import JobStoreDocument
22
23
 
@@ -545,9 +546,9 @@ class JobStore(Store):
545
546
  )
546
547
 
547
548
  @classmethod
548
- def from_file(cls: type[T], db_file: str | Path, **kwargs) -> T:
549
+ def from_file(cls, db_file: str | Path, **kwargs) -> Self:
549
550
  """
550
- Create an JobStore from a database file.
551
+ Create a JobStore from a database file.
551
552
 
552
553
  Two options are supported for the database file. The file should be in json or
553
554
  yaml format.
@@ -555,7 +556,7 @@ class JobStore(Store):
555
556
  The simplest format is a monty dumped version of the store, generated using:
556
557
 
557
558
  >>> from monty.serialization import dumpfn
558
- >>> dumpfn("job_store.yaml", job_store)
559
+ >>> dumpfn(job_store, "job_store.yaml")
559
560
 
560
561
  Alternatively, the file can contain the keys docs_store, additional_stores and
561
562
  any other keyword arguments supported by the :obj:`JobStore` constructor. The
@@ -605,7 +606,7 @@ class JobStore(Store):
605
606
  return cls.from_dict_spec(store_info, **kwargs)
606
607
 
607
608
  @classmethod
608
- def from_dict_spec(cls: type[T], spec: dict, **kwargs) -> T:
609
+ def from_dict_spec(cls, spec: dict, **kwargs) -> Self:
609
610
  """
610
611
  Create an JobStore from a dict specification.
611
612
 
@@ -5,6 +5,8 @@ from __future__ import annotations
5
5
  import typing
6
6
 
7
7
  from fireworks import FiretaskBase, Firework, FWAction, Workflow, explicit_serialize
8
+ from fireworks.utilities.fw_serializers import recursive_serialize, serialize_fw
9
+ from monty.json import jsanitize
8
10
 
9
11
  if typing.TYPE_CHECKING:
10
12
  from collections.abc import Sequence
@@ -197,3 +199,16 @@ class JobFiretask(FiretaskBase):
197
199
  defuse_workflow=response.stop_jobflow,
198
200
  defuse_children=response.stop_children,
199
201
  )
202
+
203
+ @serialize_fw
204
+ @recursive_serialize
205
+ def to_dict(self) -> dict:
206
+ """
207
+ Serialize version of the FireTask.
208
+
209
+ Overrides the original method to explicitly jsanitize the Job
210
+ to handle cases not properly handled by fireworks, like a Callable.
211
+ """
212
+ d = dict(self)
213
+ d["job"] = jsanitize(d["job"].as_dict())
214
+ return d
jobflow/managers/local.py CHANGED
@@ -16,7 +16,7 @@ logger = logging.getLogger(__name__)
16
16
  def run_locally(
17
17
  flow: jobflow.Flow | jobflow.Job | list[jobflow.Job],
18
18
  log: bool = True,
19
- store: jobflow.JobStore = None,
19
+ store: jobflow.JobStore | None = None,
20
20
  create_folders: bool = False,
21
21
  root_dir: str | Path | None = None,
22
22
  ensure_success: bool = False,
@@ -58,7 +58,7 @@ def run_locally(
58
58
  The responses of the jobs, as a dict of ``{uuid: {index: response}}``.
59
59
  """
60
60
  from collections import defaultdict
61
- from datetime import datetime
61
+ from datetime import datetime, timezone
62
62
  from pathlib import Path
63
63
  from random import randint
64
64
 
@@ -152,7 +152,7 @@ def run_locally(
152
152
 
153
153
  def _get_job_dir():
154
154
  if create_folders:
155
- time_now = datetime.utcnow().strftime(SETTINGS.DIRECTORY_FORMAT)
155
+ time_now = datetime.now(tz=timezone.utc).strftime(SETTINGS.DIRECTORY_FORMAT)
156
156
  job_dir = root_dir / f"job_{time_now}-{randint(10000, 99999)}"
157
157
  job_dir.mkdir()
158
158
  return job_dir
@@ -165,6 +165,8 @@ def run_locally(
165
165
  with cd(job_dir):
166
166
  response, jobflow_stopped = _run_job(job, parents)
167
167
 
168
+ if response is not None:
169
+ response.job_dir = job_dir
168
170
  encountered_bad_response = encountered_bad_response or response is None
169
171
  if jobflow_stopped:
170
172
  return False
jobflow/utils/__init__.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """Utility functions for logging, enumerations and manipulating dictionaries."""
2
+
2
3
  from jobflow.utils.enum import ValueEnum
3
4
  from jobflow.utils.find import (
4
5
  contains_flow_or_job,
jobflow/utils/uid.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """Tools for generating UUIDs."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from uuid import UUID
@@ -11,7 +12,7 @@ except ImportError: # pragma: no cover
11
12
  "Install it with `pip install jobflow[ulid]` or `pip install python-ulid`."
12
13
  )
13
14
 
14
- class ULID: # type: ignore
15
+ class ULID: # type: ignore[no-redef]
15
16
  """Fake ULID class for raising import error."""
16
17
 
17
18
  def __init__(self, *args, **kwargs):
jobflow/utils/uuid.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """Tools for generating UUIDs."""
2
+
2
3
  from monty.dev import deprecated
3
4
 
4
5
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jobflow
3
- Version: 0.1.17
3
+ Version: 0.1.18
4
4
  Summary: jobflow is a library for writing computational workflows
5
5
  Author-email: Alex Ganose <a.ganose@imperial.ac.uk>
6
6
  License: modified BSD
@@ -33,41 +33,44 @@ Requires-Dist: pydantic >=2.0.1
33
33
  Requires-Dist: pydash
34
34
  Provides-Extra: dev
35
35
  Requires-Dist: pre-commit >=2.12.1 ; extra == 'dev'
36
+ Requires-Dist: typing-extensions ; (python_version < "3.11") and extra == 'dev'
36
37
  Provides-Extra: docs
37
- Requires-Dist: autodoc-pydantic ==2.0.1 ; extra == 'docs'
38
- Requires-Dist: furo ==2023.9.10 ; extra == 'docs'
39
- Requires-Dist: ipython ==8.20.0 ; extra == 'docs'
40
- Requires-Dist: myst-parser ==2.0.0 ; extra == 'docs'
41
- Requires-Dist: nbsphinx ==0.9.3 ; extra == 'docs'
38
+ Requires-Dist: autodoc-pydantic ==2.1.0 ; extra == 'docs'
39
+ Requires-Dist: furo ==2024.5.6 ; extra == 'docs'
40
+ Requires-Dist: ipython ==8.26.0 ; extra == 'docs'
41
+ Requires-Dist: myst-parser ==3.0.1 ; extra == 'docs'
42
+ Requires-Dist: nbsphinx ==0.9.4 ; extra == 'docs'
42
43
  Requires-Dist: sphinx-copybutton ==0.5.2 ; extra == 'docs'
43
- Requires-Dist: sphinx ==7.2.6 ; extra == 'docs'
44
+ Requires-Dist: sphinx ==7.4.4 ; extra == 'docs'
44
45
  Provides-Extra: fireworks
45
46
  Requires-Dist: FireWorks ; extra == 'fireworks'
46
47
  Provides-Extra: strict
47
48
  Requires-Dist: FireWorks ==2.0.3 ; extra == 'strict'
48
49
  Requires-Dist: PyYAML ==6.0.1 ; extra == 'strict'
49
- Requires-Dist: maggma ==0.61.0 ; extra == 'strict'
50
- Requires-Dist: matplotlib ==3.8.2 ; extra == 'strict'
51
- Requires-Dist: monty ==2023.11.3 ; extra == 'strict'
50
+ Requires-Dist: maggma ==0.69.0 ; extra == 'strict'
51
+ Requires-Dist: matplotlib ==3.9.1 ; extra == 'strict'
52
+ Requires-Dist: monty ==2024.7.12 ; extra == 'strict'
52
53
  Requires-Dist: moto ==4.2.13 ; extra == 'strict'
53
54
  Requires-Dist: networkx ==3.2.1 ; extra == 'strict'
54
- Requires-Dist: pydantic-settings ==2.1.0 ; extra == 'strict'
55
- Requires-Dist: pydantic ==2.5.3 ; extra == 'strict'
56
- Requires-Dist: pydash ==7.0.6 ; extra == 'strict'
55
+ Requires-Dist: pydantic-settings ==2.3.4 ; extra == 'strict'
56
+ Requires-Dist: pydantic ==2.8.2 ; extra == 'strict'
57
+ Requires-Dist: pydash ==8.0.1 ; extra == 'strict'
57
58
  Requires-Dist: pydot ==2.0.0 ; extra == 'strict'
58
- Requires-Dist: typing-extensions ==4.9.0 ; extra == 'strict'
59
- Requires-Dist: python-ulid ==2.2.0 ; extra == 'strict'
59
+ Requires-Dist: python-ulid ==2.7.0 ; extra == 'strict'
60
+ Requires-Dist: typing-extensions ==4.12.2 ; extra == 'strict'
60
61
  Provides-Extra: tests
61
62
  Requires-Dist: moto ==4.2.13 ; extra == 'tests'
62
- Requires-Dist: pytest-cov ==4.1.0 ; extra == 'tests'
63
- Requires-Dist: pytest ==7.4.4 ; extra == 'tests'
63
+ Requires-Dist: pytest-cov ==5.0.0 ; extra == 'tests'
64
+ Requires-Dist: pytest ==8.2.2 ; extra == 'tests'
64
65
  Provides-Extra: ulid
65
66
  Requires-Dist: python-ulid ; extra == 'ulid'
66
67
  Provides-Extra: vis
67
68
  Requires-Dist: matplotlib ; extra == 'vis'
68
69
  Requires-Dist: pydot ; extra == 'vis'
69
70
 
70
- # jobflow
71
+ <div align="center">
72
+
73
+ # ![Jobflow](docs/_static/img/jobflow_logo.svg)
71
74
 
72
75
  [![tests](https://img.shields.io/github/actions/workflow/status/materialsproject/jobflow/testing.yml?branch=main&label=tests)](https://github.com/materialsproject/jobflow/actions?query=workflow%3Atesting)
73
76
  [![code coverage](https://img.shields.io/codecov/c/gh/materialsproject/jobflow/main)](https://codecov.io/gh/materialsproject/jobflow/)
@@ -75,11 +78,14 @@ Requires-Dist: pydot ; extra == 'vis'
75
78
  ![supported python versions](https://img.shields.io/pypi/pyversions/jobflow)
76
79
  [![DOI](https://joss.theoj.org/papers/10.21105/joss.05995/status.svg)](https://doi.org/10.21105/joss.05995)
77
80
 
81
+ </div>
82
+
78
83
  [Documentation](https://materialsproject.github.io/jobflow/) | [PyPI](https://pypi.org/project/jobflow/) | [GitHub](https://github.com/materialsproject/jobflow) | [Paper](https://doi.org/10.21105/joss.05995)
79
84
 
80
85
  Jobflow is a free, open-source library for writing and executing workflows. Complex
81
86
  workflows can be defined using simple python functions and executed locally or on
82
- arbitrary computing resources using the [FireWorks][fireworks] workflow manager.
87
+ arbitrary computing resources using the [jobflow-remote][jfr] or [FireWorks][fireworks]
88
+ workflow managers.
83
89
 
84
90
  Some features that distinguish jobflow are dynamic workflows, easy compositing and
85
91
  connecting of workflows, and the ability to store workflow outputs across multiple
@@ -98,7 +104,7 @@ Some of its features include:
98
104
  way to build complex workflows.
99
105
  - Integration with multiple databases (MongoDB, S3, GridFS, and more) through the
100
106
  [Maggma][maggma] package.
101
- - Support for the [FireWorks][fireworks] workflow management system, allowing workflow
107
+ - Support for the [jobflow-remote][jfr] and [FireWorks][fireworks] workflow management systems, allowing workflow
102
108
  execution on multicore machines or through a queue, on a single machine or multiple
103
109
  machines.
104
110
  - Support for dynamic workflows — workflows that modify themselves or create new ones
@@ -192,6 +198,7 @@ Jobflow was designed by Alex Ganose, Anubhav Jain, Gian-Marco Rignanese, David W
192
198
 
193
199
  [maggma]: https://materialsproject.github.io/maggma/
194
200
  [fireworks]: https://materialsproject.github.io/fireworks/
201
+ [jfr]: https://matgenix.github.io/jobflow-remote
195
202
  [help-forum]: https://matsci.org/c/fireworks
196
203
  [issues]: https://github.com/materialsproject/jobflow/issues
197
204
  [changelog]: https://materialsproject.github.io/jobflow/changelog.html
@@ -0,0 +1,28 @@
1
+ jobflow/__init__.py,sha256=l7o10BaqEQWw5aZziWRg40PsIAgQ4lrlluXs9hIv2mg,570
2
+ jobflow/_version.py,sha256=Ym07PBD7sAmpqVpX8tuzWma3P_Hv6KXbDKXWkw8OwaI,205
3
+ jobflow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ jobflow/settings.py,sha256=2tG3FKGTkCDgguwQZrgSt36Ll86nn4ET8ukBr2IN8Ys,5614
5
+ jobflow/core/__init__.py,sha256=3sx5t1Gysejc4c_fPrhvCjPUg0p_384Zko8ms2c_NnY,98
6
+ jobflow/core/flow.py,sha256=SEWCcw8Vs-2jRK_py720nD5SmSHh2vNtOh-LW4vu500,28939
7
+ jobflow/core/job.py,sha256=ZzlWMaTNNM5d3OaE7KDDi2jWyKNfdNNdGnnCOWKQRH8,47595
8
+ jobflow/core/maker.py,sha256=V48-StHQn7S0pFlxm281hQ0TDxQEm7BqQZ6ZuGRrB6A,11134
9
+ jobflow/core/reference.py,sha256=hLuuxQcXwMCEQk-N3jpvxnWfxJZ4OFtxK4Fb-PXMJNk,17090
10
+ jobflow/core/schemas.py,sha256=Oi5-PnZpI8S9jSY7Q4f8H7xUybbRZDXlgugeVewVsrA,968
11
+ jobflow/core/state.py,sha256=IGJTtmpotDKEcgDEnsT5x20ZeyvQT68Mr3teTjkgYnM,709
12
+ jobflow/core/store.py,sha256=PAtAhZTLU1b17OD66rqlo8_JP1p-IzH8c2WJwWd1Q2o,26997
13
+ jobflow/managers/__init__.py,sha256=KkA5cVDe2os2_2aTa8eiB9SnkGLZNybcci-Lo4tbaWM,55
14
+ jobflow/managers/fireworks.py,sha256=xKPcL1BX59jnF6LpyEwcsxvCCShLqep-9UHRyv9FmYE,7146
15
+ jobflow/managers/local.py,sha256=hVTYwwC5oxF_lMMw85xNDECI3wu-rGzJUJkQtPB_TxY,5880
16
+ jobflow/utils/__init__.py,sha256=XrA5IQ2Zm6unFRzgA58Ip9CIPchnlXm8Ei-Ny20f6NA,364
17
+ jobflow/utils/dict_mods.py,sha256=g50aMw-mK3RjXp_hHJBR9xUaWRYXoqqmPTMCPDDluz4,6052
18
+ jobflow/utils/enum.py,sha256=_buiq0NuwyYe82Ajd5-8Pjx9J63XcDDeIvLDS4evM1s,713
19
+ jobflow/utils/find.py,sha256=J57_xQ9boWVVqpbSfTECuZ3TinEXKN24LO4YWIB-7T4,6149
20
+ jobflow/utils/graph.py,sha256=UjwEklPvFz3oTiSY3E_ElYZz21ePY0xLaT7nqWDVfpI,6598
21
+ jobflow/utils/log.py,sha256=tIMpsI4JTlkpxjBZfWqZ0qkEkIxk1-RBasz8JhDcF7E,692
22
+ jobflow/utils/uid.py,sha256=hNkpJ5AYhKd_sPWE_iGPcn6YD_AyizKX_swWksFr-_M,2537
23
+ jobflow/utils/uuid.py,sha256=-cN3NpxiZuQMjl_0wq5h8ZjTYpf5o4-o2QQ5g9E7vQM,406
24
+ jobflow-0.1.18.dist-info/LICENSE,sha256=jUEiENfZNQZh9RE9ixtUWgVkLRD85ScZ6iv1WREf19w,2418
25
+ jobflow-0.1.18.dist-info/METADATA,sha256=w4Umy_IlAZmdPyFZ6srSDj_E8cYUoqp_eZaCvyCMwrM,10003
26
+ jobflow-0.1.18.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
27
+ jobflow-0.1.18.dist-info/top_level.txt,sha256=IanNooU88OupQPDrWnT0rbL3E27P2wEy7Jsfx9_j8zc,8
28
+ jobflow-0.1.18.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: setuptools (71.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,28 +0,0 @@
1
- jobflow/__init__.py,sha256=l7o10BaqEQWw5aZziWRg40PsIAgQ4lrlluXs9hIv2mg,570
2
- jobflow/_version.py,sha256=Ym07PBD7sAmpqVpX8tuzWma3P_Hv6KXbDKXWkw8OwaI,205
3
- jobflow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- jobflow/settings.py,sha256=2tG3FKGTkCDgguwQZrgSt36Ll86nn4ET8ukBr2IN8Ys,5614
5
- jobflow/core/__init__.py,sha256=3sx5t1Gysejc4c_fPrhvCjPUg0p_384Zko8ms2c_NnY,98
6
- jobflow/core/flow.py,sha256=tPMo6tCJ742XqNLiEaf0HLIZ1M9uyE8j_Uw0pEm05kg,28912
7
- jobflow/core/job.py,sha256=xeJhbjh3G7uOGq-3fN5UuLi52dKi9ifuCaogEMlYJT8,46488
8
- jobflow/core/maker.py,sha256=DKfFXe91v9rRFtgUrm8FMiEcLArmb6jnK7nysuDdZts,11185
9
- jobflow/core/reference.py,sha256=sPhV3_q8Ru-8xIoryKY8Y9oQN-1cAGVvnY08tgSAxwk,17090
10
- jobflow/core/schemas.py,sha256=Oi5-PnZpI8S9jSY7Q4f8H7xUybbRZDXlgugeVewVsrA,968
11
- jobflow/core/state.py,sha256=IGJTtmpotDKEcgDEnsT5x20ZeyvQT68Mr3teTjkgYnM,709
12
- jobflow/core/store.py,sha256=iuIQR2d4y5lmp6t7vnR2vR6TKcxfygbrKteFCGrZTgA,26971
13
- jobflow/managers/__init__.py,sha256=KkA5cVDe2os2_2aTa8eiB9SnkGLZNybcci-Lo4tbaWM,55
14
- jobflow/managers/fireworks.py,sha256=5IKDkE-dppvbhDWTfJKCMmqvxg50zBgCqm6qUqsVZtc,6654
15
- jobflow/managers/local.py,sha256=huEQBtWkYl3K7x3Ff-PL664aOZ1SXMHTRIvyIG97IgE,5771
16
- jobflow/utils/__init__.py,sha256=41l-OtHRW5J15-gilJpzilN2Tqejbb_TJYFfqxc0SPU,363
17
- jobflow/utils/dict_mods.py,sha256=g50aMw-mK3RjXp_hHJBR9xUaWRYXoqqmPTMCPDDluz4,6052
18
- jobflow/utils/enum.py,sha256=_buiq0NuwyYe82Ajd5-8Pjx9J63XcDDeIvLDS4evM1s,713
19
- jobflow/utils/find.py,sha256=J57_xQ9boWVVqpbSfTECuZ3TinEXKN24LO4YWIB-7T4,6149
20
- jobflow/utils/graph.py,sha256=UjwEklPvFz3oTiSY3E_ElYZz21ePY0xLaT7nqWDVfpI,6598
21
- jobflow/utils/log.py,sha256=tIMpsI4JTlkpxjBZfWqZ0qkEkIxk1-RBasz8JhDcF7E,692
22
- jobflow/utils/uid.py,sha256=E3L57n4V4KX0Rfd64mnuru0INAR5iQ2o8LIHBAVxXcU,2526
23
- jobflow/utils/uuid.py,sha256=DA0nEdaYGb3Mk0sHbyCdKXurens-c-HliqTIibQzk2k,405
24
- jobflow-0.1.17.dist-info/LICENSE,sha256=jUEiENfZNQZh9RE9ixtUWgVkLRD85ScZ6iv1WREf19w,2418
25
- jobflow-0.1.17.dist-info/METADATA,sha256=HJbIfYiuxQA7MZJrztdPyZftVVZZiyDLGbGYWW_Vmlc,9753
26
- jobflow-0.1.17.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
27
- jobflow-0.1.17.dist-info/top_level.txt,sha256=IanNooU88OupQPDrWnT0rbL3E27P2wEy7Jsfx9_j8zc,8
28
- jobflow-0.1.17.dist-info/RECORD,,