jobflow 0.1.19__py3-none-any.whl → 0.2.1__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
@@ -617,7 +617,7 @@ class Flow(MSONable):
617
617
  function_filter: Callable = None,
618
618
  dict_mod: bool = False,
619
619
  dynamic: bool = True,
620
- callback_filter: Callable[[Flow | Job], bool] = lambda _: True,
620
+ callback_filter: Callable[[Flow | Job], bool] | None = None,
621
621
  ):
622
622
  """
623
623
  Update the metadata of the Flow and/or its Jobs.
@@ -681,7 +681,7 @@ class Flow(MSONable):
681
681
  callback_filter=callback_filter,
682
682
  )
683
683
 
684
- if callback_filter(self) is False:
684
+ if callback_filter is not None and callback_filter(self) is False:
685
685
  return
686
686
 
687
687
  if dict_mod:
@@ -706,6 +706,7 @@ class Flow(MSONable):
706
706
  function_filter: Callable = None,
707
707
  attributes: list[str] | str = None,
708
708
  dynamic: bool = True,
709
+ dict_mod: bool = False,
709
710
  ):
710
711
  """
711
712
  Update the job config of all Jobs in the Flow.
@@ -728,6 +729,9 @@ class Flow(MSONable):
728
729
  dynamic
729
730
  The updates will be propagated to Jobs/Flows dynamically generated at
730
731
  runtime.
732
+ dict_mod
733
+ Use the dict mod language to apply updates. See :obj:`.DictMods` for more
734
+ details.
731
735
 
732
736
  Examples
733
737
  --------
@@ -767,6 +771,7 @@ class Flow(MSONable):
767
771
  function_filter=function_filter,
768
772
  attributes=attributes,
769
773
  dynamic=dynamic,
774
+ dict_mod=dict_mod,
770
775
  )
771
776
 
772
777
  def add_hosts_uuids(
jobflow/core/job.py CHANGED
@@ -926,7 +926,7 @@ class Job(MSONable):
926
926
  function_filter: Callable = None,
927
927
  dict_mod: bool = False,
928
928
  dynamic: bool = True,
929
- callback_filter: Callable[[jobflow.Flow | Job], bool] = lambda _: True,
929
+ callback_filter: Callable[[jobflow.Flow | Job], bool] | None = None,
930
930
  ):
931
931
  """
932
932
  Update the metadata of the job.
@@ -1006,7 +1006,7 @@ class Job(MSONable):
1006
1006
  ):
1007
1007
  return
1008
1008
 
1009
- if callback_filter(self) is False:
1009
+ if callback_filter is not None and callback_filter(self) is False:
1010
1010
  return
1011
1011
 
1012
1012
  # if we get to here then we pass all the filters
@@ -1022,6 +1022,7 @@ class Job(MSONable):
1022
1022
  function_filter: Callable = None,
1023
1023
  attributes: list[str] | str = None,
1024
1024
  dynamic: bool = True,
1025
+ dict_mod: bool = False,
1025
1026
  ):
1026
1027
  """
1027
1028
  Update the job config.
@@ -1045,6 +1046,9 @@ class Job(MSONable):
1045
1046
  dynamic
1046
1047
  The updates will be propagated to Jobs/Flows dynamically generated at
1047
1048
  runtime.
1049
+ dict_mod
1050
+ Use the dict mod language to apply updates. See :obj:`.DictMods` for more
1051
+ details.
1048
1052
 
1049
1053
  Examples
1050
1054
  --------
@@ -1096,12 +1100,23 @@ class Job(MSONable):
1096
1100
  At variance, if `dynamic` is set to `False` the `manager_config` option will
1097
1101
  only be set for the `test_job` and not for the generated Jobs.
1098
1102
  """
1103
+ from jobflow.utils.dict_mods import apply_mod
1104
+
1105
+ if dict_mod and attributes:
1106
+ raise ValueError("dict_mod and attributes options cannot be used together")
1107
+
1108
+ if dict_mod and isinstance(config, JobConfig):
1109
+ raise ValueError(
1110
+ "If dict_mod is selected the update config cannot be a JobConfig object"
1111
+ )
1112
+
1099
1113
  if dynamic:
1100
1114
  dict_input = {
1101
1115
  "config": config,
1102
1116
  "name_filter": name_filter,
1103
1117
  "function_filter": function_filter,
1104
1118
  "attributes": attributes,
1119
+ "dict_mod": dict_mod,
1105
1120
  }
1106
1121
  self.config_updates.append(dict_input)
1107
1122
 
@@ -1119,29 +1134,34 @@ class Job(MSONable):
1119
1134
  return
1120
1135
 
1121
1136
  # if we get to here then we pass all the filters
1122
- if isinstance(config, dict):
1123
- # convert dict specification to a JobConfig but set the attributes
1124
- if attributes is None:
1125
- attributes = list(config.keys())
1126
-
1127
- attributes = [attributes] if isinstance(attributes, str) else attributes
1128
- if not set(attributes).issubset(set(config.keys())):
1129
- raise ValueError(
1130
- "Specified attributes include a key that is not present in the "
1131
- "config dictionary."
1132
- )
1133
- config = JobConfig(**config)
1134
-
1135
- if attributes is None:
1136
- # overwrite the whole config
1137
- self.config = config
1137
+ if dict_mod:
1138
+ conf_dict = self.config.as_dict()
1139
+ apply_mod(config, conf_dict)
1140
+ self.config = JobConfig.from_dict(conf_dict)
1138
1141
  else:
1139
- # only update the specified attributes
1140
- attributes = [attributes] if isinstance(attributes, str) else attributes
1141
- for attr in attributes:
1142
- if not hasattr(self.config, attr):
1143
- raise ValueError(f"Unknown JobConfig attribute: {attr}")
1144
- setattr(self.config, attr, getattr(config, attr))
1142
+ if isinstance(config, dict):
1143
+ # convert dict specification to a JobConfig but set the attributes
1144
+ if attributes is None:
1145
+ attributes = list(config.keys())
1146
+
1147
+ attributes = [attributes] if isinstance(attributes, str) else attributes
1148
+ if not set(attributes).issubset(set(config.keys())):
1149
+ raise ValueError(
1150
+ "Specified attributes include a key that is not present in the "
1151
+ "config dictionary."
1152
+ )
1153
+ config = JobConfig(**config)
1154
+
1155
+ if attributes is None:
1156
+ # overwrite the whole config
1157
+ self.config = config
1158
+ else:
1159
+ # only update the specified attributes
1160
+ attributes = [attributes] if isinstance(attributes, str) else attributes
1161
+ for attr in attributes:
1162
+ if not hasattr(self.config, attr):
1163
+ raise ValueError(f"Unknown JobConfig attribute: {attr}")
1164
+ setattr(self.config, attr, getattr(config, attr))
1145
1165
 
1146
1166
  def as_dict(self) -> dict:
1147
1167
  """Serialize the job as a dictionary."""
@@ -1265,7 +1285,7 @@ class Response(typing.Generic[T]):
1265
1285
  job_returns.output = apply_schema(job_returns.output, output_schema)
1266
1286
 
1267
1287
  job_returns.job_dir = job_dir
1268
- return cast(Self, job_returns)
1288
+ return cast("Self", job_returns)
1269
1289
 
1270
1290
  if isinstance(job_returns, (list, tuple)):
1271
1291
  # check that a Response object is not given as one of many outputs
jobflow/core/reference.py CHANGED
@@ -513,7 +513,7 @@ def validate_schema_access(
513
513
  the bool is ``True`` if the schema access was valid.
514
514
  The BaseModel class associated with the item, if any.
515
515
  """
516
- schema_dict = schema.schema()
516
+ schema_dict = schema.model_json_schema()
517
517
  if item not in schema_dict["properties"]:
518
518
  raise AttributeError(f"{schema.__name__} does not have attribute '{item}'.")
519
519
 
jobflow/utils/graph.py CHANGED
@@ -170,7 +170,7 @@ def to_pydot(flow: jobflow.Flow):
170
170
  if isinstance(job, Flow):
171
171
  add_cluster(job, cluster)
172
172
  else:
173
- cluster.add_node(pydot_graph.get_node(f'"{job.uuid}"')[0])
173
+ cluster.add_node(pydot_graph.get_node(f"{job.uuid}")[0])
174
174
 
175
175
  outer_graph.add_subgraph(cluster)
176
176
 
jobflow/utils/uuid.py CHANGED
@@ -4,7 +4,10 @@ from monty.dev import deprecated
4
4
 
5
5
 
6
6
  @deprecated(
7
- message="The UUID system will be replace with UID that contains both UUID and ULID."
7
+ message=(
8
+ "The UUID system will be replaced with a UID that "
9
+ "contains both the UUID and ULID."
10
+ )
8
11
  )
9
12
  def suuid() -> str:
10
13
  """
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: jobflow
3
- Version: 0.1.19
3
+ Version: 0.2.1
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
@@ -17,56 +17,58 @@ Classifier: Operating System :: OS Independent
17
17
  Classifier: Programming Language :: Python :: 3
18
18
  Classifier: Programming Language :: Python :: 3.10
19
19
  Classifier: Programming Language :: Python :: 3.11
20
- Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
21
22
  Classifier: Topic :: Database :: Front-Ends
22
23
  Classifier: Topic :: Other/Nonlisted Topic
23
24
  Classifier: Topic :: Scientific/Engineering
24
- Requires-Python: >=3.9
25
+ Requires-Python: >=3.10
25
26
  Description-Content-Type: text/markdown
26
27
  License-File: LICENSE
27
- Requires-Dist: PyYAML
28
- Requires-Dist: maggma>=0.57.0
28
+ Requires-Dist: PyYAML>=6.0.1
29
+ Requires-Dist: maggma>=0.72.0
29
30
  Requires-Dist: monty>=2023.9.25
30
- Requires-Dist: networkx
31
+ Requires-Dist: networkx>=3.2.1
31
32
  Requires-Dist: pydantic-settings>=2.0.3
32
- Requires-Dist: pydantic>=2.0.1
33
- Requires-Dist: pydash
33
+ Requires-Dist: pydantic>=2.4
34
+ Requires-Dist: pydash>=8.0.1
34
35
  Provides-Extra: ulid
35
36
  Requires-Dist: python-ulid; extra == "ulid"
36
37
  Provides-Extra: docs
37
- Requires-Dist: autodoc_pydantic==2.1.0; extra == "docs"
38
- Requires-Dist: furo==2024.8.6; extra == "docs"
39
- Requires-Dist: ipython==8.29.0; extra == "docs"
40
- Requires-Dist: myst_parser==4.0.0; extra == "docs"
41
- Requires-Dist: nbsphinx==0.9.5; extra == "docs"
38
+ Requires-Dist: autodoc_pydantic==2.2.0; extra == "docs"
39
+ Requires-Dist: furo==2025.9.25; extra == "docs"
40
+ Requires-Dist: ipython==9.3.0; extra == "docs"
41
+ Requires-Dist: myst_parser==4.0.1; extra == "docs"
42
+ Requires-Dist: nbsphinx==0.9.7; extra == "docs"
42
43
  Requires-Dist: sphinx-copybutton==0.5.2; extra == "docs"
43
44
  Requires-Dist: sphinx==8.1.3; extra == "docs"
44
45
  Provides-Extra: dev
45
46
  Requires-Dist: pre-commit>=2.12.1; extra == "dev"
46
47
  Requires-Dist: typing_extensions; python_version < "3.11" and extra == "dev"
47
48
  Provides-Extra: tests
48
- Requires-Dist: moto==4.2.13; extra == "tests"
49
- Requires-Dist: pytest-cov==6.0.0; extra == "tests"
50
- Requires-Dist: pytest==8.3.3; extra == "tests"
49
+ Requires-Dist: moto==5.1.16; extra == "tests"
50
+ Requires-Dist: pytest-cov==7.0.0; extra == "tests"
51
+ Requires-Dist: pytest==8.4.2; extra == "tests"
51
52
  Provides-Extra: vis
52
53
  Requires-Dist: matplotlib; extra == "vis"
53
54
  Requires-Dist: pydot; extra == "vis"
54
55
  Provides-Extra: fireworks
55
56
  Requires-Dist: FireWorks; extra == "fireworks"
56
57
  Provides-Extra: strict
57
- Requires-Dist: FireWorks==2.0.3; extra == "strict"
58
- Requires-Dist: PyYAML==6.0.2; extra == "strict"
59
- Requires-Dist: maggma==0.70.0; extra == "strict"
60
- Requires-Dist: matplotlib==3.9.2; extra == "strict"
61
- Requires-Dist: monty==2024.10.21; extra == "strict"
62
- Requires-Dist: moto==4.2.13; extra == "strict"
63
- Requires-Dist: networkx==3.2.1; extra == "strict"
64
- Requires-Dist: pydantic-settings==2.6.1; extra == "strict"
65
- Requires-Dist: pydantic==2.9.2; extra == "strict"
66
- Requires-Dist: pydash==8.0.4; extra == "strict"
67
- Requires-Dist: pydot==2.0.0; extra == "strict"
68
- Requires-Dist: python-ulid==3.0.0; extra == "strict"
69
- Requires-Dist: typing-extensions==4.12.2; extra == "strict"
58
+ Requires-Dist: FireWorks==2.0.6; extra == "strict"
59
+ Requires-Dist: PyYAML==6.0.3; extra == "strict"
60
+ Requires-Dist: maggma==0.72.0; extra == "strict"
61
+ Requires-Dist: matplotlib==3.10.7; extra == "strict"
62
+ Requires-Dist: monty==2025.3.3; extra == "strict"
63
+ Requires-Dist: moto==5.1.16; extra == "strict"
64
+ Requires-Dist: networkx==3.4.2; extra == "strict"
65
+ Requires-Dist: pydantic-settings==2.11.0; extra == "strict"
66
+ Requires-Dist: pydantic==2.12.3; extra == "strict"
67
+ Requires-Dist: pydash==8.0.5; extra == "strict"
68
+ Requires-Dist: pydot==4.0.1; extra == "strict"
69
+ Requires-Dist: python-ulid==3.1.0; extra == "strict"
70
+ Requires-Dist: typing-extensions==4.15.0; extra == "strict"
71
+ Dynamic: license-file
70
72
 
71
73
  <div align="center">
72
74
 
@@ -3,10 +3,10 @@ jobflow/_version.py,sha256=Ym07PBD7sAmpqVpX8tuzWma3P_Hv6KXbDKXWkw8OwaI,205
3
3
  jobflow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  jobflow/settings.py,sha256=yinHpix-DPwzcBhQCO8zDXFuv048rmBgpYMPa9wcs8c,6094
5
5
  jobflow/core/__init__.py,sha256=3sx5t1Gysejc4c_fPrhvCjPUg0p_384Zko8ms2c_NnY,98
6
- jobflow/core/flow.py,sha256=XuH0-n8DpSWLHyUdVU7KeewtDzjZw7AIqh9xwLQkqcc,30634
7
- jobflow/core/job.py,sha256=wAVmJrWO5sf7vze8696lMLz_A-bnPVgIp5TvhmDIGx0,48145
6
+ jobflow/core/flow.py,sha256=AWseNK4P42CiiPykl4kud0e-SJYxDJoqM6I_n77w4_M,30854
7
+ jobflow/core/job.py,sha256=ogKour02EF6uvSYZz4F4zaqiM6bUiaCwwtboF0WprPk,49002
8
8
  jobflow/core/maker.py,sha256=WhsYw2wDNVIyAEeRUoikOQMzXzHuXfFVwXrJpwGCD1E,11162
9
- jobflow/core/reference.py,sha256=hLuuxQcXwMCEQk-N3jpvxnWfxJZ4OFtxK4Fb-PXMJNk,17090
9
+ jobflow/core/reference.py,sha256=2xqNwyo57wFPLMLPprXa5h8f_cOWcyCHmDsfVEl5pRk,17101
10
10
  jobflow/core/schemas.py,sha256=Oi5-PnZpI8S9jSY7Q4f8H7xUybbRZDXlgugeVewVsrA,968
11
11
  jobflow/core/state.py,sha256=IGJTtmpotDKEcgDEnsT5x20ZeyvQT68Mr3teTjkgYnM,709
12
12
  jobflow/core/store.py,sha256=PAtAhZTLU1b17OD66rqlo8_JP1p-IzH8c2WJwWd1Q2o,26997
@@ -17,12 +17,12 @@ jobflow/utils/__init__.py,sha256=XrA5IQ2Zm6unFRzgA58Ip9CIPchnlXm8Ei-Ny20f6NA,364
17
17
  jobflow/utils/dict_mods.py,sha256=g50aMw-mK3RjXp_hHJBR9xUaWRYXoqqmPTMCPDDluz4,6052
18
18
  jobflow/utils/enum.py,sha256=_buiq0NuwyYe82Ajd5-8Pjx9J63XcDDeIvLDS4evM1s,713
19
19
  jobflow/utils/find.py,sha256=J57_xQ9boWVVqpbSfTECuZ3TinEXKN24LO4YWIB-7T4,6149
20
- jobflow/utils/graph.py,sha256=UjwEklPvFz3oTiSY3E_ElYZz21ePY0xLaT7nqWDVfpI,6598
20
+ jobflow/utils/graph.py,sha256=kweAowEzv8ZGjJ9KZvJ-G5ueAqGPWbU0z7Xd4e-q8no,6596
21
21
  jobflow/utils/log.py,sha256=4-_1OUSQ8I4Q6CgQ4pxNBeveBdpXla7nibZNF7Vk3pw,1110
22
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.19.dist-info/LICENSE,sha256=jUEiENfZNQZh9RE9ixtUWgVkLRD85ScZ6iv1WREf19w,2418
25
- jobflow-0.1.19.dist-info/METADATA,sha256=HrT82LwLIk0FvQTJqg_ZNSyr8xHqe-PV1TL-RiVX_eM,9945
26
- jobflow-0.1.19.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
27
- jobflow-0.1.19.dist-info/top_level.txt,sha256=IanNooU88OupQPDrWnT0rbL3E27P2wEy7Jsfx9_j8zc,8
28
- jobflow-0.1.19.dist-info/RECORD,,
23
+ jobflow/utils/uuid.py,sha256=m0fInOs1yklpavf7jId85luDOHjZqfIIUzEtd89Bk_s,440
24
+ jobflow-0.2.1.dist-info/licenses/LICENSE,sha256=jUEiENfZNQZh9RE9ixtUWgVkLRD85ScZ6iv1WREf19w,2418
25
+ jobflow-0.2.1.dist-info/METADATA,sha256=4B39RQEMtBLt7_K2rghR9VfZ4GfxgFHIig9iixQRdaw,10039
26
+ jobflow-0.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
+ jobflow-0.2.1.dist-info/top_level.txt,sha256=IanNooU88OupQPDrWnT0rbL3E27P2wEy7Jsfx9_j8zc,8
28
+ jobflow-0.2.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5