torchx-nightly 2025.10.13__py3-none-any.whl → 2025.10.15__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.

Potentially problematic release.


This version of torchx-nightly might be problematic. Click here for more details.

torchx/cli/cmd_run.py CHANGED
@@ -26,7 +26,7 @@ from torchx.cli.cmd_log import get_logs
26
26
  from torchx.runner import config, get_runner, Runner
27
27
  from torchx.runner.config import load_sections
28
28
  from torchx.schedulers import get_default_scheduler_name, get_scheduler_factories
29
- from torchx.specs import CfgVal
29
+ from torchx.specs import CfgVal, Workspace
30
30
  from torchx.specs.finder import (
31
31
  _Component,
32
32
  ComponentNotFoundException,
@@ -36,7 +36,6 @@ from torchx.specs.finder import (
36
36
  )
37
37
  from torchx.util.log_tee_helpers import tee_logs
38
38
  from torchx.util.types import none_throws
39
- from torchx.workspace import Workspace
40
39
 
41
40
 
42
41
  MISSING_COMPONENT_ERROR_MSG = (
torchx/runner/api.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env python3
2
1
  # Copyright (c) Meta Platforms, Inc. and affiliates.
3
2
  # All rights reserved.
4
3
  #
@@ -43,6 +42,7 @@ from torchx.specs import (
43
42
  parse_app_handle,
44
43
  runopts,
45
44
  UnknownAppException,
45
+ Workspace,
46
46
  )
47
47
  from torchx.specs.finder import get_component
48
48
  from torchx.tracker.api import (
@@ -54,7 +54,7 @@ from torchx.tracker.api import (
54
54
  from torchx.util.session import get_session_id_or_create_new, TORCHX_INTERNAL_SESSION_ID
55
55
 
56
56
  from torchx.util.types import none_throws
57
- from torchx.workspace.api import Workspace, WorkspaceMixin
57
+ from torchx.workspace import WorkspaceMixin
58
58
 
59
59
  if TYPE_CHECKING:
60
60
  from typing_extensions import Self
torchx/schedulers/api.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env python3
2
1
  # Copyright (c) Meta Platforms, Inc. and affiliates.
3
2
  # All rights reserved.
4
3
  #
@@ -22,8 +21,9 @@ from torchx.specs import (
22
21
  Role,
23
22
  RoleStatus,
24
23
  runopts,
24
+ Workspace,
25
25
  )
26
- from torchx.workspace.api import Workspace, WorkspaceMixin
26
+ from torchx.workspace import WorkspaceMixin
27
27
 
28
28
 
29
29
  DAYS_IN_2_WEEKS = 14
torchx/specs/__init__.py CHANGED
@@ -12,6 +12,8 @@ used by components to define the apps which can then be launched via a TorchX
12
12
  scheduler or pipeline adapter.
13
13
  """
14
14
  import difflib
15
+
16
+ import os
15
17
  from typing import Callable, Dict, Mapping, Optional
16
18
 
17
19
  from torchx.specs.api import (
@@ -64,8 +66,10 @@ AWS_NAMED_RESOURCES: Mapping[str, ResourceFactory] = import_attr(
64
66
  GENERIC_NAMED_RESOURCES: Mapping[str, ResourceFactory] = import_attr(
65
67
  "torchx.specs.named_resources_generic", "NAMED_RESOURCES", default={}
66
68
  )
67
- FB_NAMED_RESOURCES: Mapping[str, ResourceFactory] = import_attr(
68
- "torchx.specs.fb.named_resources", "NAMED_RESOURCES", default={}
69
+ CUSTOM_NAMED_RESOURCES: Mapping[str, ResourceFactory] = import_attr(
70
+ os.environ.get("TORCHX_CUSTOM_NAMED_RESOURCES", "torchx.specs.fb.named_resources"),
71
+ "NAMED_RESOURCES",
72
+ default={},
69
73
  )
70
74
 
71
75
 
@@ -76,7 +80,7 @@ def _load_named_resources() -> Dict[str, Callable[[], Resource]]:
76
80
  for name, resource in {
77
81
  **GENERIC_NAMED_RESOURCES,
78
82
  **AWS_NAMED_RESOURCES,
79
- **FB_NAMED_RESOURCES,
83
+ **CUSTOM_NAMED_RESOURCES,
80
84
  **resource_methods,
81
85
  }.items():
82
86
  materialized_resources[name] = resource
torchx/specs/api.py CHANGED
@@ -891,10 +891,14 @@ class runopt:
891
891
  Represents the metadata about the specific run option
892
892
  """
893
893
 
894
+ class alias(str):
895
+ pass
896
+
894
897
  default: CfgVal
895
898
  opt_type: Type[CfgVal]
896
899
  is_required: bool
897
900
  help: str
901
+ aliases: list[alias] | None = None
898
902
 
899
903
  @property
900
904
  def is_type_list_of_str(self) -> bool:
@@ -986,6 +990,7 @@ class runopts:
986
990
 
987
991
  def __init__(self) -> None:
988
992
  self._opts: Dict[str, runopt] = {}
993
+ self._alias_to_key: dict[runopt.alias, str] = {}
989
994
 
990
995
  def __iter__(self) -> Iterator[Tuple[str, runopt]]:
991
996
  return self._opts.items().__iter__()
@@ -1013,9 +1018,16 @@ class runopts:
1013
1018
 
1014
1019
  def get(self, name: str) -> Optional[runopt]:
1015
1020
  """
1016
- Returns option if any was registered, or None otherwise
1021
+ Returns option if any was registered, or None otherwise.
1022
+ First searches for the option by ``name``, then falls-back to matching ``name`` with any
1023
+ registered aliases.
1024
+
1017
1025
  """
1018
- return self._opts.get(name, None)
1026
+ if name in self._opts:
1027
+ return self._opts[name]
1028
+ if name in self._alias_to_key:
1029
+ return self._opts[self._alias_to_key[name]]
1030
+ return None
1019
1031
 
1020
1032
  def resolve(self, cfg: Mapping[str, CfgVal]) -> Dict[str, CfgVal]:
1021
1033
  """
@@ -1030,6 +1042,24 @@ class runopts:
1030
1042
 
1031
1043
  for cfg_key, runopt in self._opts.items():
1032
1044
  val = resolved_cfg.get(cfg_key)
1045
+ resolved_name = None
1046
+ aliases = runopt.aliases or []
1047
+ if val is None:
1048
+ for alias in aliases:
1049
+ val = resolved_cfg.get(alias)
1050
+ if alias in cfg or val is not None:
1051
+ resolved_name = alias
1052
+ break
1053
+ else:
1054
+ resolved_name = cfg_key
1055
+ for alias in aliases:
1056
+ duplicate_val = resolved_cfg.get(alias)
1057
+ if alias in cfg or duplicate_val is not None:
1058
+ raise InvalidRunConfigException(
1059
+ f"Duplicate opt name. runopt: `{resolved_name}``, is an alias of runopt: `{alias}`",
1060
+ resolved_name,
1061
+ cfg,
1062
+ )
1033
1063
 
1034
1064
  # check required opt
1035
1065
  if runopt.is_required and val is None:
@@ -1049,7 +1079,7 @@ class runopts:
1049
1079
  )
1050
1080
 
1051
1081
  # not required and not set, set to default
1052
- if val is None:
1082
+ if val is None and resolved_name is None:
1053
1083
  resolved_cfg[cfg_key] = runopt.default
1054
1084
  return resolved_cfg
1055
1085
 
@@ -1142,9 +1172,38 @@ class runopts:
1142
1172
  cfg[key] = val
1143
1173
  return cfg
1144
1174
 
1175
+ def _get_primary_key_and_aliases(
1176
+ self,
1177
+ cfg_key: list[str] | str,
1178
+ ) -> tuple[str, list[runopt.alias]]:
1179
+ """
1180
+ Returns the primary key and aliases for the given cfg_key.
1181
+ """
1182
+ if isinstance(cfg_key, str):
1183
+ return cfg_key, []
1184
+
1185
+ if len(cfg_key) == 0:
1186
+ raise ValueError("cfg_key must be a non-empty list")
1187
+ primary_key = None
1188
+ aliases = list[runopt.alias]()
1189
+ for name in cfg_key:
1190
+ if isinstance(name, runopt.alias):
1191
+ aliases.append(name)
1192
+ else:
1193
+ if primary_key is not None:
1194
+ raise ValueError(
1195
+ f" Given more than one primary key: {primary_key}, {name}. Please use runopt.alias type for aliases. "
1196
+ )
1197
+ primary_key = name
1198
+ if primary_key is None or primary_key == "":
1199
+ raise ValueError(
1200
+ "Missing cfg_key. Please provide one other than the aliases."
1201
+ )
1202
+ return primary_key, aliases
1203
+
1145
1204
  def add(
1146
1205
  self,
1147
- cfg_key: str,
1206
+ cfg_key: str | list[str],
1148
1207
  type_: Type[CfgVal],
1149
1208
  help: str,
1150
1209
  default: CfgVal = None,
@@ -1155,6 +1214,7 @@ class runopts:
1155
1214
  value (if any). If the ``default`` is not specified then this option
1156
1215
  is a required option.
1157
1216
  """
1217
+ primary_key, aliases = self._get_primary_key_and_aliases(cfg_key)
1158
1218
  if required and default is not None:
1159
1219
  raise ValueError(
1160
1220
  f"Required option: {cfg_key} must not specify default value. Given: {default}"
@@ -1165,8 +1225,10 @@ class runopts:
1165
1225
  f"Option: {cfg_key}, must be of type: {type_}."
1166
1226
  f" Given: {default} ({type(default).__name__})"
1167
1227
  )
1168
-
1169
- self._opts[cfg_key] = runopt(default, type_, required, help)
1228
+ opt = runopt(default, type_, required, help, aliases)
1229
+ for alias in aliases:
1230
+ self._alias_to_key[alias] = primary_key
1231
+ self._opts[primary_key] = opt
1170
1232
 
1171
1233
  def update(self, other: "runopts") -> None:
1172
1234
  self._opts.update(other._opts)
@@ -120,6 +120,16 @@ def aws_p5_48xlarge() -> Resource:
120
120
  )
121
121
 
122
122
 
123
+ def aws_p5e_48xlarge() -> Resource:
124
+ return Resource(
125
+ cpu=192,
126
+ gpu=8,
127
+ memMB=2048 * GiB,
128
+ capabilities={K8S_ITYPE: "p5e.48xlarge"},
129
+ devices={EFA_DEVICE: 32},
130
+ )
131
+
132
+
123
133
  def aws_p5en_48xlarge() -> Resource:
124
134
  return Resource(
125
135
  cpu=192,
@@ -419,6 +429,7 @@ NAMED_RESOURCES: Mapping[str, Callable[[], Resource]] = {
419
429
  "aws_p4d.24xlarge": aws_p4d_24xlarge,
420
430
  "aws_p4de.24xlarge": aws_p4de_24xlarge,
421
431
  "aws_p5.48xlarge": aws_p5_48xlarge,
432
+ "aws_p5e.48xlarge": aws_p5e_48xlarge,
422
433
  "aws_p5en.48xlarge": aws_p5en_48xlarge,
423
434
  "aws_g4dn.xlarge": aws_g4dn_xlarge,
424
435
  "aws_g4dn.2xlarge": aws_g4dn_2xlarge,
@@ -22,4 +22,4 @@ Example workspace paths:
22
22
  * ``memory://foo-bar/`` an in-memory workspace for notebook/programmatic usage
23
23
  """
24
24
 
25
- from torchx.workspace.api import walk_workspace, Workspace, WorkspaceMixin # noqa: F401
25
+ from torchx.workspace.api import walk_workspace, WorkspaceMixin # noqa: F401
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: torchx-nightly
3
- Version: 2025.10.13
3
+ Version: 2025.10.15
4
4
  Summary: TorchX SDK and Components
5
5
  Home-page: https://github.com/meta-pytorch/torchx
6
6
  Author: TorchX Devs
@@ -16,7 +16,7 @@ torchx/cli/cmd_configure.py,sha256=1kTv0qbsbV44So74plAySwWu56pQrqjhfW_kbfdC3Rw,1
16
16
  torchx/cli/cmd_describe.py,sha256=E5disbHoKTsqYKp2s3DaFW9GDLCCOgdOc3pQoHKoyCs,1283
17
17
  torchx/cli/cmd_list.py,sha256=alkS9aIaDI8lX3W8uj8Vtr3IU3G2VeCuokKSd3zOFug,1409
18
18
  torchx/cli/cmd_log.py,sha256=v-EZYUDOcG95rEgTnrsmPJMUyxM9Mk8YFAJtUxtgViE,5475
19
- torchx/cli/cmd_run.py,sha256=XDsPQ5xf9z0Q-QWv808jO_L_HcYH89NN3gq8mFfF2Mo,18808
19
+ torchx/cli/cmd_run.py,sha256=z8wS-M2W9hHZfLkA6DFiV6Y0LFS9KfEBc_NTwAwdviQ,18780
20
20
  torchx/cli/cmd_runopts.py,sha256=NWZiP8XpQjfTDJgays2c6MgL_8wxFoeDge6NstaZdKk,1302
21
21
  torchx/cli/cmd_status.py,sha256=22IAEmKs0qkG6kJi83u9dRX2Q-ntT7yehVx7FxtY-vQ,2114
22
22
  torchx/cli/cmd_tracker.py,sha256=9gmOmYi-89qQRGQfSrXCTto7ve54_JKFqs_wa7oRUA8,5223
@@ -48,7 +48,7 @@ torchx/examples/apps/lightning/profiler.py,sha256=SSSihnwjeUTkBoz0E3qn1b-wbkfUIo
48
48
  torchx/examples/apps/lightning/train.py,sha256=0wvvshGHvZowePB4LfclXwn40X7i9euM0ReETWBcPSo,6253
49
49
  torchx/pipelines/__init__.py,sha256=2MbRVk5xwRjg-d2qPemeXpEhDsocMQumPQ53lsesZAI,606
50
50
  torchx/runner/__init__.py,sha256=x8Sz7s_tLxPgJgvWIhK4ju9BNZU61uBFywGwDY6CqJs,315
51
- torchx/runner/api.py,sha256=KydGtgeSwJwbqcDnI5fZ0MCuijDlzfeoSCRiDef8RCE,31294
51
+ torchx/runner/api.py,sha256=jxtgOl7nNOqpzG-sjUJngXhIOachqaVfKu9rF8YqHWI,31271
52
52
  torchx/runner/config.py,sha256=SaKOB50d79WaMFPWK8CC4as6UaNFaRGhrBkfajq3KC4,18311
53
53
  torchx/runner/events/__init__.py,sha256=cMiNjnr4eUNQ2Nxxtu4nsvN5lu56b-a6nJ-ct3i7DQk,5536
54
54
  torchx/runner/events/api.py,sha256=bvxKBAYK8LzbrBNaNLgL1x0aivtfANmWo1EMGOrSR8k,2668
@@ -57,7 +57,7 @@ torchx/runtime/__init__.py,sha256=Wxje2BryzeQneFu5r6P9JJiEKG-_C9W1CcZ_JNrKT6g,59
57
57
  torchx/runtime/tracking/__init__.py,sha256=dYnAPnrXYREfPXkpHhdOFkcYIODWEbA13PdD-wLQYBo,3055
58
58
  torchx/runtime/tracking/api.py,sha256=SmUQyUKZqG3KlAhT7CJOGqRz1O274E4m63wQeOVq3CU,5472
59
59
  torchx/schedulers/__init__.py,sha256=FQN9boQM4mwOD3sK9LZ3GBgw-gJ7Vx4MFj6z6ATQIrc,2211
60
- torchx/schedulers/api.py,sha256=lfxNhrEO6eYYqVuQzzj9sTXrZShuZkyYxJ1jPE-Lvpo,14561
60
+ torchx/schedulers/api.py,sha256=5Amli1httEl82XebAqd8vl3dM8zMKwYfRgfd0mEq3is,14538
61
61
  torchx/schedulers/aws_batch_scheduler.py,sha256=-HpjNVhSFBDxZo3cebK-3YEguB49dxoaud2gz30cAVM,29437
62
62
  torchx/schedulers/aws_sagemaker_scheduler.py,sha256=flN8GumKE2Dz4X_foAt6Jnvt-ZVojWs6pcyrHwB0hz0,20921
63
63
  torchx/schedulers/devices.py,sha256=RjVcu22ZRl_9OKtOtmA1A3vNXgu2qD6A9ST0L0Hsg4I,1734
@@ -69,12 +69,12 @@ torchx/schedulers/local_scheduler.py,sha256=ttnxFDy48_DSYDEW-no27OirFZOyfrjwJ2S1
69
69
  torchx/schedulers/lsf_scheduler.py,sha256=YS6Yel8tXJqLPxbcGz95lZG2nCi36AQXdNDyuBJePKg,17661
70
70
  torchx/schedulers/slurm_scheduler.py,sha256=vypGaCZe61bkyNkqRlK4Iwmk_NaAUQi-DsspaWd6BZw,31873
71
71
  torchx/schedulers/streams.py,sha256=8_SLezgnWgfv_zXUsJCUM34-h2dtv25NmZuxEwkzmxw,2007
72
- torchx/specs/__init__.py,sha256=XpyR3PPcv5IwZg5iX18KDoRhDFqUoQm7o4ANo6lOo78,6683
73
- torchx/specs/api.py,sha256=BbZbNSvPnpC2KOfVC5_oIR-AE730ArRUeUyFyyTKxh4,45329
72
+ torchx/specs/__init__.py,sha256=SXS4r_roOkbbAL-p7EY5fl5ou-AG7S9Ck-zKtRBdHOk,6760
73
+ torchx/specs/api.py,sha256=ICKsTWxEats9IwWXUm-D1NJy4jyONMV2zdrWfUrpKNg,47827
74
74
  torchx/specs/builders.py,sha256=Ye3of4MupJ-da8vLaX6_-nzGo_FRw1BFpYsX6dAZCNk,13730
75
75
  torchx/specs/file_linter.py,sha256=z0c4mKJv47BWiPaWCdUM0A8kHwnj4b1s7oTmESuD9Tc,14407
76
76
  torchx/specs/finder.py,sha256=gWQNEFrLYqrZoI0gMMhQ70YAC4sxqS0ZFpoWAmcVi44,17438
77
- torchx/specs/named_resources_aws.py,sha256=28B1e_sSJbqmzApBMMJvOUKaIFPm1jj04-Nqt0Z30Xw,11425
77
+ torchx/specs/named_resources_aws.py,sha256=ZNAbw6lD8NUlMfcJ-LpX14dMSaHO7m4Yt9iHwAF44yg,11674
78
78
  torchx/specs/named_resources_generic.py,sha256=Sg4tAdqiiWDrDz2Lj_pnfsjzGIXKTou73wPseh6j55w,2646
79
79
  torchx/specs/test/components/__init__.py,sha256=J8qjUOysmcMAek2KFN13mViOXZxTYc5vCrF02t3VuFU,223
80
80
  torchx/specs/test/components/a/__init__.py,sha256=kdxEgnI8QBSBiuTjaB4qDD7JX84hWowyPWU4B2Cqe9A,561
@@ -98,13 +98,13 @@ torchx/util/session.py,sha256=r6M_nyzXgcbk1GgYGZ324F_ehRGCqjjdVk4YgKxMj8M,1214
98
98
  torchx/util/shlex.py,sha256=eXEKu8KC3zIcd8tEy9_s8Ds5oma8BORr-0VGWNpG2dk,463
99
99
  torchx/util/strings.py,sha256=7Ef1loz2IYMrzeJ6Lewywi5cBIc3X3g7lSPbT1Tn_z4,664
100
100
  torchx/util/types.py,sha256=E9dxAWQnsJkIDuHtg-poeOJ4etucSI_xP_Z5kNJX8uI,9229
101
- torchx/workspace/__init__.py,sha256=cZsKVvUWwDYcGhe6SCXQGBQfbk_yTnKEImOkI6xmu30,809
101
+ torchx/workspace/__init__.py,sha256=FqN8AN4VhR1C_SBY10MggQvNZmyanbbuPuE-JCjkyUY,798
102
102
  torchx/workspace/api.py,sha256=h2SaC-pYPBLuo3XtkXJ0APMoro-C-ry7KucI7r3EUf4,8753
103
103
  torchx/workspace/dir_workspace.py,sha256=npNW_IjUZm_yS5r-8hrRkH46ndDd9a_eApT64m1S1T4,2268
104
104
  torchx/workspace/docker_workspace.py,sha256=PFu2KQNVC-0p2aKJ-W_BKA9ZOmXdCY2ABEkCExp3udQ,10269
105
- torchx_nightly-2025.10.13.dist-info/LICENSE,sha256=WVHfXhFC0Ia8LTKt_nJVYobdqTJVg_4J3Crrfm2A8KQ,1721
106
- torchx_nightly-2025.10.13.dist-info/METADATA,sha256=0gIrjPBZLLdMhE1rUsmJzTecPK_zuyxVh2ZwNLvNdRQ,5069
107
- torchx_nightly-2025.10.13.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
108
- torchx_nightly-2025.10.13.dist-info/entry_points.txt,sha256=T328AMXeKI3JZnnxfkEew2ZcMN1oQDtkXjMz7lkV-P4,169
109
- torchx_nightly-2025.10.13.dist-info/top_level.txt,sha256=pxew3bc2gsiViS0zADs0jb6kC5v8o_Yy_85fhHj_J1A,7
110
- torchx_nightly-2025.10.13.dist-info/RECORD,,
105
+ torchx_nightly-2025.10.15.dist-info/LICENSE,sha256=WVHfXhFC0Ia8LTKt_nJVYobdqTJVg_4J3Crrfm2A8KQ,1721
106
+ torchx_nightly-2025.10.15.dist-info/METADATA,sha256=TzPu_BGlpYuU43FKQXVFz1N6AAHidhAmgRSrcCMKCuA,5069
107
+ torchx_nightly-2025.10.15.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
108
+ torchx_nightly-2025.10.15.dist-info/entry_points.txt,sha256=T328AMXeKI3JZnnxfkEew2ZcMN1oQDtkXjMz7lkV-P4,169
109
+ torchx_nightly-2025.10.15.dist-info/top_level.txt,sha256=pxew3bc2gsiViS0zADs0jb6kC5v8o_Yy_85fhHj_J1A,7
110
+ torchx_nightly-2025.10.15.dist-info/RECORD,,