runnable 0.30.2__py3-none-any.whl → 0.30.4__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.
@@ -94,7 +94,9 @@ class AnyPathCatalog(BaseCatalog):
94
94
 
95
95
  return data_catalogs
96
96
 
97
- def put(self, name: str) -> List[DataCatalog]:
97
+ def put(
98
+ self, name: str, allow_file_not_found_exc: bool = False
99
+ ) -> List[DataCatalog]:
98
100
  """
99
101
  Put the files matching the glob pattern into the catalog.
100
102
 
@@ -154,7 +156,7 @@ class AnyPathCatalog(BaseCatalog):
154
156
  # TODO: Think about syncing only if the file is changed
155
157
  self.upload_to_catalog(file)
156
158
 
157
- if not data_catalogs:
159
+ if not data_catalogs and not allow_file_not_found_exc:
158
160
  raise Exception(f"Did not find any files matching {name} in {copy_from}")
159
161
 
160
162
  return data_catalogs
@@ -139,6 +139,7 @@ class GenericJobExecutor(BaseJobExecutor):
139
139
  def _sync_catalog(
140
140
  self,
141
141
  catalog_settings=Optional[List[str]],
142
+ allow_file_not_found_exc: bool = False,
142
143
  ) -> List[DataCatalog] | None:
143
144
  if not catalog_settings:
144
145
  logger.info("No catalog settings found")
@@ -147,7 +148,7 @@ class GenericJobExecutor(BaseJobExecutor):
147
148
  data_catalogs = []
148
149
  for name_pattern in catalog_settings:
149
150
  data_catalog = self._context.catalog_handler.put(
150
- name=name_pattern,
151
+ name=name_pattern, allow_file_not_found_exc=allow_file_not_found_exc
151
152
  )
152
153
 
153
154
  logger.debug(f"Added data catalog: {data_catalog} to job log")
@@ -7,7 +7,6 @@ from kubernetes import client
7
7
  from kubernetes import config as k8s_config
8
8
  from pydantic import BaseModel, ConfigDict, Field, PlainSerializer, PrivateAttr
9
9
  from pydantic.alias_generators import to_camel
10
- from rich import print
11
10
 
12
11
  from extensions.job_executor import GenericJobExecutor
13
12
  from runnable import console, defaults, utils
@@ -223,8 +222,13 @@ class GenericK8sJobExecutor(GenericJobExecutor):
223
222
  job_log.status = attempt_log.status
224
223
  job_log.attempts.append(attempt_log)
225
224
 
225
+ allow_file_not_found_exc = True
226
+ if job_log.status == defaults.SUCCESS:
227
+ allow_file_not_found_exc = False
228
+
226
229
  data_catalogs_put: Optional[List[DataCatalog]] = self._sync_catalog(
227
- catalog_settings=catalog_settings
230
+ catalog_settings=catalog_settings,
231
+ allow_file_not_found_exc=allow_file_not_found_exc,
228
232
  )
229
233
  logger.debug(f"data_catalogs_put: {data_catalogs_put}")
230
234
 
@@ -55,11 +55,16 @@ class LocalJobExecutor(GenericJobExecutor):
55
55
  job_log.status = attempt_log.status
56
56
  job_log.attempts.append(attempt_log)
57
57
 
58
+ allow_file_not_found_exc = True
59
+ if job_log.status == defaults.SUCCESS:
60
+ allow_file_not_found_exc = False
61
+
58
62
  data_catalogs_put: Optional[List[DataCatalog]] = self._sync_catalog(
59
- catalog_settings=catalog_settings
63
+ catalog_settings=catalog_settings,
64
+ allow_file_not_found_exc=allow_file_not_found_exc,
60
65
  )
61
- logger.debug(f"data_catalogs_put: {data_catalogs_put}")
62
66
 
67
+ logger.debug(f"data_catalogs_put: {data_catalogs_put}")
63
68
  job_log.add_data_catalogs(data_catalogs_put or [])
64
69
 
65
70
  console.print("Summary of job")
@@ -64,9 +64,15 @@ class LocalContainerJobExecutor(GenericJobExecutor):
64
64
  job_log.status = attempt_log.status
65
65
  job_log.attempts.append(attempt_log)
66
66
 
67
+ allow_file_not_found_exc = True
68
+ if job_log.status == defaults.SUCCESS:
69
+ allow_file_not_found_exc = False
70
+
67
71
  data_catalogs_put: Optional[List[DataCatalog]] = self._sync_catalog(
68
- catalog_settings=catalog_settings
72
+ catalog_settings=catalog_settings,
73
+ allow_file_not_found_exc=allow_file_not_found_exc,
69
74
  )
75
+
70
76
  logger.debug(f"data_catalogs_put: {data_catalogs_put}")
71
77
 
72
78
  job_log.add_data_catalogs(data_catalogs_put or [])
extensions/nodes/torch.py CHANGED
@@ -1,6 +1,8 @@
1
1
  import importlib
2
2
  import logging
3
3
  import os
4
+ import random
5
+ import string
4
6
  from datetime import datetime
5
7
  from typing import Any, Callable
6
8
 
@@ -28,7 +30,13 @@ def training_subprocess():
28
30
  command = os.environ.get("RUNNABLE_TORCH_COMMAND")
29
31
  run_id = os.environ.get("RUNNABLE_TORCH_RUN_ID", "")
30
32
  parameters_files = os.environ.get("RUNNABLE_TORCH_PARAMETERS_FILES", "")
31
- process_run_id = run_id + "-" + os.environ.get("RANK", "")
33
+ process_run_id = (
34
+ run_id
35
+ + "-"
36
+ + os.environ.get("RANK", "")
37
+ + "-"
38
+ + "".join(random.choices(string.ascii_lowercase, k=3))
39
+ )
32
40
 
33
41
  delete_env_vars_with_prefix("RUNNABLE_")
34
42
 
@@ -40,6 +48,13 @@ def training_subprocess():
40
48
  job_id=process_run_id,
41
49
  )
42
50
 
51
+ from runnable.context import run_context
52
+
53
+ job_log = run_context.run_log_store.get_run_log_by_id(run_id=run_context.run_id)
54
+
55
+ if job_log.status == defaults.FAIL:
56
+ raise Exception(f"Job {process_run_id} failed")
57
+
43
58
 
44
59
  def get_callable_from_dotted_path(dotted_path) -> Callable:
45
60
  try:
@@ -111,7 +111,7 @@ class GenericPipelineExecutor(BasePipelineExecutor):
111
111
  )
112
112
 
113
113
  def _sync_catalog(
114
- self, stage: str, synced_catalogs=None
114
+ self, stage: str, synced_catalogs=None, allow_file_no_found_exc: bool = False
115
115
  ) -> Optional[List[DataCatalog]]:
116
116
  """
117
117
  1). Identify the catalog settings by over-riding node settings with the global settings.
@@ -160,7 +160,7 @@ class GenericPipelineExecutor(BasePipelineExecutor):
160
160
 
161
161
  elif stage == "put":
162
162
  data_catalog = self._context.catalog_handler.put(
163
- name=name_pattern,
163
+ name=name_pattern, allow_file_not_found_exc=allow_file_no_found_exc
164
164
  )
165
165
  else:
166
166
  raise Exception(f"Stage {stage} not supported")
@@ -233,12 +233,16 @@ class GenericPipelineExecutor(BasePipelineExecutor):
233
233
  mock=mock,
234
234
  )
235
235
 
236
+ allow_file_not_found_exc = True
236
237
  if step_log.status == defaults.SUCCESS:
237
- data_catalogs_put: Optional[List[DataCatalog]] = self._sync_catalog(
238
- stage="put"
239
- )
240
- logger.debug(f"data_catalogs_put: {data_catalogs_put}")
241
- step_log.add_data_catalogs(data_catalogs_put or [])
238
+ # raise exception if we succeeded but the file was not found
239
+ allow_file_not_found_exc = False
240
+
241
+ data_catalogs_put: Optional[List[DataCatalog]] = self._sync_catalog(
242
+ stage="put", allow_file_no_found_exc=allow_file_not_found_exc
243
+ )
244
+ logger.debug(f"data_catalogs_put: {data_catalogs_put}")
245
+ step_log.add_data_catalogs(data_catalogs_put or [])
242
246
 
243
247
  # get catalog should always be added to the step log
244
248
  step_log.add_data_catalogs(data_catalogs_get or [])
@@ -658,7 +658,7 @@ class ArgoExecutor(GenericPipelineExecutor):
658
658
  def _set_env_vars_to_task(
659
659
  self, working_on: BaseNode, container_template: CoreContainerTemplate
660
660
  ):
661
- if not isinstance(working_on, TaskNode) or isinstance(working_on, TorchNode):
661
+ if not (isinstance(working_on, TaskNode) or isinstance(working_on, TorchNode)):
662
662
  return
663
663
 
664
664
  global_envs: dict[str, str] = {}
runnable/catalog.py CHANGED
@@ -76,7 +76,9 @@ class BaseCatalog(ABC, BaseModel):
76
76
  raise NotImplementedError
77
77
 
78
78
  @abstractmethod
79
- def put(self, name: str) -> List[DataCatalog]:
79
+ def put(
80
+ self, name: str, allow_file_not_found_exc: bool = False
81
+ ) -> List[DataCatalog]:
80
82
  """
81
83
  Put the file by 'name' from the 'compute_data_folder' in the catalog for the run_id.
82
84
 
@@ -137,7 +139,9 @@ class DoNothingCatalog(BaseCatalog):
137
139
  logger.info("Using a do-nothing catalog, doing nothing in get")
138
140
  return []
139
141
 
140
- def put(self, name: str) -> List[DataCatalog]:
142
+ def put(
143
+ self, name: str, allow_file_not_found_exc: bool = False
144
+ ) -> List[DataCatalog]:
141
145
  """
142
146
  Does nothing
143
147
  """
runnable/executor.py CHANGED
@@ -123,6 +123,7 @@ class BaseJobExecutor(BaseExecutor):
123
123
  def _sync_catalog(
124
124
  self,
125
125
  catalog_settings: Optional[List[str]],
126
+ allow_file_not_found_exc: bool = False,
126
127
  ) -> Optional[List[DataCatalog]]:
127
128
  """
128
129
  1). Identify the catalog settings by over-riding node settings with the global settings.
@@ -175,7 +176,10 @@ class BasePipelineExecutor(BaseExecutor):
175
176
 
176
177
  @abstractmethod
177
178
  def _sync_catalog(
178
- self, stage: str, synced_catalogs=None
179
+ self,
180
+ stage: str,
181
+ synced_catalogs=None,
182
+ allow_file_no_found_exc: bool = False,
179
183
  ) -> Optional[List[DataCatalog]]:
180
184
  """
181
185
  1). Identify the catalog settings by over-riding node settings with the global settings.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: runnable
3
- Version: 0.30.2
3
+ Version: 0.30.4
4
4
  Summary: Add your description here
5
5
  Author-email: "Vammi, Vijay" <vijay.vammi@astrazeneca.com>
6
6
  License-File: LICENSE
@@ -1,26 +1,26 @@
1
1
  extensions/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  extensions/catalog/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- extensions/catalog/any_path.py,sha256=aNjphoPIyllUfY2uNDFWD1ErM3Px6izSGr0-oGowN8k,7263
4
+ extensions/catalog/any_path.py,sha256=atB5gWPRX6ptW6zwYeCVb_fh0qhs7WAFO9HIsnMZl98,7350
5
5
  extensions/catalog/file_system.py,sha256=T_qFPFfrmykoAMc1rjNi_DBb437me8WPRcFglwAK744,1767
6
6
  extensions/catalog/minio.py,sha256=R3GvfCxN1GTcs4bQIAWh79_GHDTVd14gnpKlzwFeKUI,2363
7
7
  extensions/catalog/pyproject.toml,sha256=lLNxY6v04c8I5QK_zKw_E6sJTArSJRA_V-79ktaA3Hk,279
8
8
  extensions/catalog/s3.py,sha256=Sw5t8_kVRprn3uGGJCiHn7M9zw1CLaCOFj6YErtfG0o,287
9
9
  extensions/job_executor/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- extensions/job_executor/__init__.py,sha256=E2R6GV5cZTlZdqA5SVJ6ajZFh4oruM0k8AKHkpOZ3W8,5772
11
- extensions/job_executor/k8s.py,sha256=erzw4UOsOf2JSOiQio5stgW_rMryAsIQSBd8wiL6nBY,16214
10
+ extensions/job_executor/__init__.py,sha256=VeLuYCcShCIYT0TNtAXfUF9tOk4ZHoLzdTEvbsz0spM,5870
11
+ extensions/job_executor/k8s.py,sha256=0V7BL7ERmonVMgCsO-J57cxH__v8KomwukMwepH3qgs,16388
12
12
  extensions/job_executor/k8s_job_spec.yaml,sha256=7aFpxHdO_p6Hkc3YxusUOuAQTD1Myu0yTPX9DrhxbOg,1158
13
- extensions/job_executor/local.py,sha256=3v6F8SOaPbCfPVVmU07RFr1wgs8iC8WoSn6Evfi8o3M,2033
14
- extensions/job_executor/local_container.py,sha256=8-dLhzY34pOVjJ_x0VmeTwVvYkESXBnp4j-XLsSsgBk,6688
13
+ extensions/job_executor/local.py,sha256=3ZbCFXBvbLlMp10JTmQJJrjBKG2keHI6SH8hEvmHDkA,2230
14
+ extensions/job_executor/local_container.py,sha256=1JcLJ0zrNSNHdubrSO9miN54iwvPLHqKMZ08aOC8WWo,6886
15
15
  extensions/job_executor/pyproject.toml,sha256=UIEgiCYHTXcRWSByNMFuKJFKgxTBpQqTqyUecIsb_Vc,286
16
16
  extensions/nodes/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  extensions/nodes/nodes.py,sha256=s9ub1dqy4qHjRQG6YElCdL7rCOTYNs9RUIrStZ6tEB4,28256
18
18
  extensions/nodes/pyproject.toml,sha256=YTu-ETN3JNFSkMzzWeOwn4m-O2nbRH-PmiPBALDCUw4,278
19
- extensions/nodes/torch.py,sha256=oYh4ep9J6CS3r04HURJba5m4v8lzNupWUh4PAXvGgi0,5952
19
+ extensions/nodes/torch.py,sha256=id0_HVkRcqL9_DPOI-b53vaDwRgVfGB-zZS3yrRej9g,6318
20
20
  extensions/nodes/torch_config.py,sha256=yDvDADpnLhQsNtfH8qIztLHQ2LhYiOJEWljxpH9GZzs,1222
21
21
  extensions/pipeline_executor/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- extensions/pipeline_executor/__init__.py,sha256=LApJGwJctEBTDQX9gGHkGV97T6rF_q-_59OzvAJ2X1g,24346
23
- extensions/pipeline_executor/argo.py,sha256=-mWH5H2lZEldO8er7-tHberm7swqo4CwrtQKUd2VkGA,37944
22
+ extensions/pipeline_executor/__init__.py,sha256=wfigTL2T9OHrmE8b2Ydmb8h6hr-oF--Yc2FectC7WaY,24623
23
+ extensions/pipeline_executor/argo.py,sha256=AEGSWVZulBL6EsvbVCaeBeTl2m_t5ymc6RFpMKhivis,37946
24
24
  extensions/pipeline_executor/local.py,sha256=6oWUJ6b6NvIkpeQJBoCT1hbfX4_6WCB4HzMgHZ4ik1A,1887
25
25
  extensions/pipeline_executor/local_container.py,sha256=3kZ2QCsrq_YjH9dcAz8v05knKShQ_JtbIU-IA_-G538,12724
26
26
  extensions/pipeline_executor/mocked.py,sha256=0sMmypuvstBIv9uQg-WAcPrF3oOFpeEXNi6N8Nzdnl0,5680
@@ -41,14 +41,14 @@ extensions/secrets/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
41
41
  extensions/secrets/dotenv.py,sha256=nADHXI6KJ_LUYOIe5EbtYH-21OBebSNVr0Pjb1GlZ7w,1573
42
42
  extensions/secrets/pyproject.toml,sha256=mLJNImNcBlbLKHh-0ugVWT9V83R4RibyyYDtBCSqVF4,282
43
43
  runnable/__init__.py,sha256=swvqdCjeddn40o4zjsluyahdVcU0r1arSRrxmRsvFEQ,673
44
- runnable/catalog.py,sha256=W_erYbLZ-ffuA9RQuWVqz1DUJOuWayf32ne32IDbAbc,4358
44
+ runnable/catalog.py,sha256=4msQxLhLKlsDDrHFnGauPYe-Or-q9g8_RYCn_4dpxaU,4466
45
45
  runnable/cli.py,sha256=3BiKSj95h2Drn__YlchMPZ5rBMafuRb2OGIsVpbsO5Y,8788
46
46
  runnable/context.py,sha256=by5uepmuCP0dmM9BmsliXihSes5QEFejwAsmekcqylE,1388
47
47
  runnable/datastore.py,sha256=ZobM1aVkgeUJ2fZYt63IFDsoNzObwc93hdByegS5YKQ,32396
48
48
  runnable/defaults.py,sha256=3o9IVGryyCE6PoQTOoaIaHHTbJGEzmdXMcwzOhwAYoI,3518
49
49
  runnable/entrypoints.py,sha256=cDbhtmLUWdBh9K6hNusfQpSd5NadcX8V1K2JEDf_YAg,18984
50
50
  runnable/exceptions.py,sha256=LFbp0-Qxg2PAMLEVt7w2whhBxSG-5pzUEv5qN-Rc4_c,3003
51
- runnable/executor.py,sha256=J8-Ri9nBZCb-ao6okePb9FUVlhAaPc0ojQ2l48-FUqc,15031
51
+ runnable/executor.py,sha256=UOsYJ3NkTGw4FTR0iePX7AOJzY7vODhZ62aqrwVMO1c,15143
52
52
  runnable/graph.py,sha256=poQz5zcvq89ju_u5sYlunQLPbHnXTaUmjcvstPwvT4U,16536
53
53
  runnable/names.py,sha256=vn92Kv9ANROYSZX6Z4z1v_WA3WiEdIYmG6KEStBFZug,8134
54
54
  runnable/nodes.py,sha256=d1eLttMAcV7CTwTEqOuNwZqItANoLUkXJ73Xp-srlyI,17811
@@ -58,8 +58,8 @@ runnable/sdk.py,sha256=NZVQGaL4Zm2hwloRmqEgp8UPbBg9hY1abQGYnOgniPI,35128
58
58
  runnable/secrets.py,sha256=4L_dBFxTgr8r_hHUD6RlZEtqaOHDRsFG5PXO5wlvMI0,2324
59
59
  runnable/tasks.py,sha256=Qb1IhVxHv68E7vf3M3YCf7MGRHyjmsEEYBpEpiZ4mRI,29062
60
60
  runnable/utils.py,sha256=hBr7oGwGL2VgfITlQCTz-a1iwvvf7Mfl-HY8UdENZac,19929
61
- runnable-0.30.2.dist-info/METADATA,sha256=M-3XWv_ijqZLfEwzQ6W5IsZaHGOpNxToI8pYNI-SlwQ,10115
62
- runnable-0.30.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
63
- runnable-0.30.2.dist-info/entry_points.txt,sha256=PrjKrlfXPZaV_7hz8orGu4FDnatLqnhPOXljyllszdw,1880
64
- runnable-0.30.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
65
- runnable-0.30.2.dist-info/RECORD,,
61
+ runnable-0.30.4.dist-info/METADATA,sha256=S-5zecrqE4tU5MW4Fe1-2F-Q_hLU7fAXZ2oo9xVRRUw,10115
62
+ runnable-0.30.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
63
+ runnable-0.30.4.dist-info/entry_points.txt,sha256=PrjKrlfXPZaV_7hz8orGu4FDnatLqnhPOXljyllszdw,1880
64
+ runnable-0.30.4.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
65
+ runnable-0.30.4.dist-info/RECORD,,