torchx-nightly 2025.7.2__py3-none-any.whl → 2025.7.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.
Potentially problematic release.
This version of torchx-nightly might be problematic. Click here for more details.
- torchx/components/structured_arg.py +2 -3
- torchx/runner/api.py +16 -3
- torchx/schedulers/__init__.py +3 -4
- torchx/schedulers/api.py +0 -1
- torchx/schedulers/aws_batch_scheduler.py +2 -2
- torchx/schedulers/aws_sagemaker_scheduler.py +2 -3
- torchx/schedulers/docker_scheduler.py +2 -3
- torchx/schedulers/gcp_batch_scheduler.py +10 -4
- torchx/schedulers/kubernetes_mcad_scheduler.py +8 -7
- torchx/schedulers/kubernetes_scheduler.py +2 -2
- torchx/schedulers/local_scheduler.py +2 -2
- torchx/schedulers/lsf_scheduler.py +2 -3
- torchx/schedulers/ray_scheduler.py +21 -4
- torchx/schedulers/slurm_scheduler.py +2 -3
- torchx/util/entrypoints.py +36 -11
- torchx/util/types.py +33 -27
- {torchx_nightly-2025.7.2.dist-info → torchx_nightly-2025.7.4.dist-info}/METADATA +2 -3
- {torchx_nightly-2025.7.2.dist-info → torchx_nightly-2025.7.4.dist-info}/RECORD +22 -22
- {torchx_nightly-2025.7.2.dist-info → torchx_nightly-2025.7.4.dist-info}/LICENSE +0 -0
- {torchx_nightly-2025.7.2.dist-info → torchx_nightly-2025.7.4.dist-info}/WHEEL +0 -0
- {torchx_nightly-2025.7.2.dist-info → torchx_nightly-2025.7.4.dist-info}/entry_points.txt +0 -0
- {torchx_nightly-2025.7.2.dist-info → torchx_nightly-2025.7.4.dist-info}/top_level.txt +0 -0
|
@@ -30,8 +30,6 @@ from dataclasses import dataclass
|
|
|
30
30
|
from pathlib import Path
|
|
31
31
|
from typing import Optional
|
|
32
32
|
|
|
33
|
-
from pyre_extensions import none_throws
|
|
34
|
-
|
|
35
33
|
from torchx import specs
|
|
36
34
|
|
|
37
35
|
|
|
@@ -148,7 +146,8 @@ class StructuredNameArgument:
|
|
|
148
146
|
if m: # use the last module name
|
|
149
147
|
run_name = m.rpartition(".")[2]
|
|
150
148
|
else: # use script name w/ no extension
|
|
151
|
-
|
|
149
|
+
assert script, "`script` can't be `None` here due checks above"
|
|
150
|
+
run_name = Path(script).stem
|
|
152
151
|
return StructuredNameArgument(
|
|
153
152
|
experiment_name or default_experiment_name, run_name
|
|
154
153
|
)
|
torchx/runner/api.py
CHANGED
|
@@ -14,7 +14,18 @@ import time
|
|
|
14
14
|
import warnings
|
|
15
15
|
from datetime import datetime
|
|
16
16
|
from types import TracebackType
|
|
17
|
-
from typing import
|
|
17
|
+
from typing import (
|
|
18
|
+
Any,
|
|
19
|
+
Dict,
|
|
20
|
+
Iterable,
|
|
21
|
+
List,
|
|
22
|
+
Mapping,
|
|
23
|
+
Optional,
|
|
24
|
+
Tuple,
|
|
25
|
+
Type,
|
|
26
|
+
TYPE_CHECKING,
|
|
27
|
+
TypeVar,
|
|
28
|
+
)
|
|
18
29
|
|
|
19
30
|
from torchx.runner.events import log_event
|
|
20
31
|
from torchx.schedulers import get_scheduler_factories, SchedulerFactory
|
|
@@ -43,7 +54,9 @@ from torchx.util.session import get_session_id_or_create_new, TORCHX_INTERNAL_SE
|
|
|
43
54
|
|
|
44
55
|
from torchx.util.types import none_throws
|
|
45
56
|
from torchx.workspace.api import PkgInfo, WorkspaceBuilder, WorkspaceMixin
|
|
46
|
-
|
|
57
|
+
|
|
58
|
+
if TYPE_CHECKING:
|
|
59
|
+
from typing_extensions import Self
|
|
47
60
|
|
|
48
61
|
from .config import get_config, get_configs
|
|
49
62
|
|
|
@@ -121,7 +134,7 @@ class Runner:
|
|
|
121
134
|
scheduler_params[lower_case_key.strip("torchx_")] = value
|
|
122
135
|
return scheduler_params
|
|
123
136
|
|
|
124
|
-
def __enter__(self) -> Self:
|
|
137
|
+
def __enter__(self) -> "Self":
|
|
125
138
|
return self
|
|
126
139
|
|
|
127
140
|
def __exit__(
|
torchx/schedulers/__init__.py
CHANGED
|
@@ -8,11 +8,10 @@
|
|
|
8
8
|
# pyre-strict
|
|
9
9
|
|
|
10
10
|
import importlib
|
|
11
|
-
from typing import
|
|
11
|
+
from typing import Mapping, Protocol
|
|
12
12
|
|
|
13
13
|
from torchx.schedulers.api import Scheduler
|
|
14
14
|
from torchx.util.entrypoints import load_group
|
|
15
|
-
from typing_extensions import Protocol
|
|
16
15
|
|
|
17
16
|
DEFAULT_SCHEDULER_MODULES: Mapping[str, str] = {
|
|
18
17
|
"local_docker": "torchx.schedulers.docker_scheduler",
|
|
@@ -44,7 +43,7 @@ def _defer_load_scheduler(path: str) -> SchedulerFactory:
|
|
|
44
43
|
|
|
45
44
|
def get_scheduler_factories(
|
|
46
45
|
group: str = "torchx.schedulers", skip_defaults: bool = False
|
|
47
|
-
) ->
|
|
46
|
+
) -> dict[str, SchedulerFactory]:
|
|
48
47
|
"""
|
|
49
48
|
get_scheduler_factories returns all the available schedulers names under `group` and the
|
|
50
49
|
method to instantiate them.
|
|
@@ -52,7 +51,7 @@ def get_scheduler_factories(
|
|
|
52
51
|
The first scheduler in the dictionary is used as the default scheduler.
|
|
53
52
|
"""
|
|
54
53
|
|
|
55
|
-
default_schedulers:
|
|
54
|
+
default_schedulers: dict[str, SchedulerFactory] = {}
|
|
56
55
|
for scheduler, path in DEFAULT_SCHEDULER_MODULES.items():
|
|
57
56
|
default_schedulers[scheduler] = _defer_load_scheduler(path)
|
|
58
57
|
|
torchx/schedulers/api.py
CHANGED
|
@@ -53,13 +53,13 @@ from typing import (
|
|
|
53
53
|
Optional,
|
|
54
54
|
Tuple,
|
|
55
55
|
TYPE_CHECKING,
|
|
56
|
+
TypedDict,
|
|
56
57
|
TypeVar,
|
|
57
58
|
)
|
|
58
59
|
|
|
59
60
|
import torchx
|
|
60
61
|
import yaml
|
|
61
62
|
from torchx.schedulers.api import (
|
|
62
|
-
AppDryRunInfo,
|
|
63
63
|
DescribeAppResponse,
|
|
64
64
|
filter_regex,
|
|
65
65
|
ListAppResponse,
|
|
@@ -71,6 +71,7 @@ from torchx.schedulers.devices import get_device_mounts
|
|
|
71
71
|
from torchx.schedulers.ids import make_unique
|
|
72
72
|
from torchx.specs.api import (
|
|
73
73
|
AppDef,
|
|
74
|
+
AppDryRunInfo,
|
|
74
75
|
AppState,
|
|
75
76
|
BindMount,
|
|
76
77
|
CfgVal,
|
|
@@ -86,7 +87,6 @@ from torchx.specs.api import (
|
|
|
86
87
|
from torchx.specs.named_resources_aws import instance_type_from_resource
|
|
87
88
|
from torchx.util.types import none_throws
|
|
88
89
|
from torchx.workspace.docker_workspace import DockerWorkspaceMixin
|
|
89
|
-
from typing_extensions import TypedDict
|
|
90
90
|
|
|
91
91
|
ENV_TORCHX_ROLE_IDX = "TORCHX_ROLE_IDX"
|
|
92
92
|
|
|
@@ -25,6 +25,7 @@ from typing import (
|
|
|
25
25
|
OrderedDict,
|
|
26
26
|
Tuple,
|
|
27
27
|
TYPE_CHECKING,
|
|
28
|
+
TypedDict,
|
|
28
29
|
TypeVar,
|
|
29
30
|
)
|
|
30
31
|
|
|
@@ -34,16 +35,14 @@ import yaml
|
|
|
34
35
|
from sagemaker.pytorch import PyTorch
|
|
35
36
|
from torchx.components.structured_arg import StructuredNameArgument
|
|
36
37
|
from torchx.schedulers.api import (
|
|
37
|
-
AppDryRunInfo,
|
|
38
38
|
DescribeAppResponse,
|
|
39
39
|
ListAppResponse,
|
|
40
40
|
Scheduler,
|
|
41
41
|
Stream,
|
|
42
42
|
)
|
|
43
43
|
from torchx.schedulers.ids import make_unique
|
|
44
|
-
from torchx.specs.api import AppDef, AppState, CfgVal, runopts
|
|
44
|
+
from torchx.specs.api import AppDef, AppDryRunInfo, AppState, CfgVal, runopts
|
|
45
45
|
from torchx.workspace.docker_workspace import DockerWorkspaceMixin
|
|
46
|
-
from typing_extensions import TypedDict
|
|
47
46
|
|
|
48
47
|
|
|
49
48
|
if TYPE_CHECKING:
|
|
@@ -13,12 +13,11 @@ import re
|
|
|
13
13
|
import tempfile
|
|
14
14
|
from dataclasses import dataclass
|
|
15
15
|
from datetime import datetime
|
|
16
|
-
from typing import Any, Dict, Iterable, List, Optional, TYPE_CHECKING, Union
|
|
16
|
+
from typing import Any, Dict, Iterable, List, Optional, TYPE_CHECKING, TypedDict, Union
|
|
17
17
|
|
|
18
18
|
import torchx
|
|
19
19
|
import yaml
|
|
20
20
|
from torchx.schedulers.api import (
|
|
21
|
-
AppDryRunInfo,
|
|
22
21
|
DescribeAppResponse,
|
|
23
22
|
filter_regex,
|
|
24
23
|
ListAppResponse,
|
|
@@ -30,6 +29,7 @@ from torchx.schedulers.devices import get_device_mounts
|
|
|
30
29
|
from torchx.schedulers.ids import make_unique
|
|
31
30
|
from torchx.specs.api import (
|
|
32
31
|
AppDef,
|
|
32
|
+
AppDryRunInfo,
|
|
33
33
|
AppState,
|
|
34
34
|
BindMount,
|
|
35
35
|
DeviceMount,
|
|
@@ -42,7 +42,6 @@ from torchx.specs.api import (
|
|
|
42
42
|
VolumeMount,
|
|
43
43
|
)
|
|
44
44
|
from torchx.workspace.docker_workspace import DockerWorkspaceMixin
|
|
45
|
-
from typing_extensions import TypedDict
|
|
46
45
|
|
|
47
46
|
|
|
48
47
|
if TYPE_CHECKING:
|
|
@@ -24,22 +24,28 @@ See https://cloud.google.com/batch/docs/get-started#prerequisites
|
|
|
24
24
|
|
|
25
25
|
from dataclasses import dataclass
|
|
26
26
|
from datetime import datetime
|
|
27
|
-
from typing import Any, Dict, Iterable, List, Optional, TYPE_CHECKING
|
|
27
|
+
from typing import Any, Dict, Iterable, List, Optional, TYPE_CHECKING, TypedDict
|
|
28
28
|
|
|
29
29
|
import torchx
|
|
30
30
|
import yaml
|
|
31
31
|
|
|
32
32
|
from torchx.schedulers.api import (
|
|
33
|
-
AppDryRunInfo,
|
|
34
33
|
DescribeAppResponse,
|
|
35
34
|
ListAppResponse,
|
|
36
35
|
Scheduler,
|
|
37
36
|
Stream,
|
|
38
37
|
)
|
|
39
38
|
from torchx.schedulers.ids import make_unique
|
|
40
|
-
from torchx.specs.api import
|
|
39
|
+
from torchx.specs.api import (
|
|
40
|
+
AppDef,
|
|
41
|
+
AppDryRunInfo,
|
|
42
|
+
AppState,
|
|
43
|
+
macros,
|
|
44
|
+
Resource,
|
|
45
|
+
Role,
|
|
46
|
+
runopts,
|
|
47
|
+
)
|
|
41
48
|
from torchx.util.strings import normalize_str
|
|
42
|
-
from typing_extensions import TypedDict
|
|
43
49
|
|
|
44
50
|
|
|
45
51
|
if TYPE_CHECKING:
|
|
@@ -17,8 +17,8 @@ Prerequisites
|
|
|
17
17
|
|
|
18
18
|
TorchX Kubernetes_MCAD scheduler depends on AppWrapper + MCAD.
|
|
19
19
|
|
|
20
|
-
Install MCAD:
|
|
21
|
-
See deploying Multi-Cluster-Application-Dispatcher guide
|
|
20
|
+
Install MCAD:
|
|
21
|
+
See deploying Multi-Cluster-Application-Dispatcher guide
|
|
22
22
|
https://github.com/project-codeflare/multi-cluster-app-dispatcher/blob/main/doc/deploy/deployment.md
|
|
23
23
|
|
|
24
24
|
This implementation requires MCAD v1.34.1 or higher.
|
|
@@ -46,12 +46,12 @@ from typing import (
|
|
|
46
46
|
Optional,
|
|
47
47
|
Tuple,
|
|
48
48
|
TYPE_CHECKING,
|
|
49
|
+
TypedDict,
|
|
49
50
|
)
|
|
50
51
|
|
|
51
52
|
import torchx
|
|
52
53
|
import yaml
|
|
53
54
|
from torchx.schedulers.api import (
|
|
54
|
-
AppDryRunInfo,
|
|
55
55
|
DescribeAppResponse,
|
|
56
56
|
filter_regex,
|
|
57
57
|
ListAppResponse,
|
|
@@ -62,6 +62,7 @@ from torchx.schedulers.api import (
|
|
|
62
62
|
from torchx.schedulers.ids import make_unique
|
|
63
63
|
from torchx.specs.api import (
|
|
64
64
|
AppDef,
|
|
65
|
+
AppDryRunInfo,
|
|
65
66
|
AppState,
|
|
66
67
|
BindMount,
|
|
67
68
|
CfgVal,
|
|
@@ -78,7 +79,6 @@ from torchx.specs.api import (
|
|
|
78
79
|
)
|
|
79
80
|
|
|
80
81
|
from torchx.workspace.docker_workspace import DockerWorkspaceMixin
|
|
81
|
-
from typing_extensions import TypedDict
|
|
82
82
|
|
|
83
83
|
if TYPE_CHECKING:
|
|
84
84
|
from docker import DockerClient
|
|
@@ -600,7 +600,7 @@ def app_to_resource(
|
|
|
600
600
|
|
|
601
601
|
"""
|
|
602
602
|
Create Service:
|
|
603
|
-
The selector will have the key 'appwrapper.workload.codeflare.dev', and the value will be
|
|
603
|
+
The selector will have the key 'appwrapper.workload.codeflare.dev', and the value will be
|
|
604
604
|
the appwrapper name
|
|
605
605
|
"""
|
|
606
606
|
|
|
@@ -797,7 +797,8 @@ class KubernetesMCADOpts(TypedDict, total=False):
|
|
|
797
797
|
|
|
798
798
|
|
|
799
799
|
class KubernetesMCADScheduler(
|
|
800
|
-
DockerWorkspaceMixin,
|
|
800
|
+
DockerWorkspaceMixin,
|
|
801
|
+
Scheduler[KubernetesMCADOpts, AppDef, AppDryRunInfo[KubernetesMCADJob]],
|
|
801
802
|
):
|
|
802
803
|
"""
|
|
803
804
|
KubernetesMCADScheduler is a TorchX scheduling interface to Kubernetes.
|
|
@@ -994,7 +995,7 @@ class KubernetesMCADScheduler(
|
|
|
994
995
|
if image_secret is not None and service_account is not None:
|
|
995
996
|
msg = """Service Account and Image Secret names are both provided.
|
|
996
997
|
Depending on the Service Account configuration, an ImagePullSecret may be defined in your Service Account.
|
|
997
|
-
If this is the case, check service account and image secret configurations to understand the expected behavior for
|
|
998
|
+
If this is the case, check service account and image secret configurations to understand the expected behavior for
|
|
998
999
|
patched image push access."""
|
|
999
1000
|
warnings.warn(msg)
|
|
1000
1001
|
namespace = cfg.get("namespace")
|
|
@@ -44,12 +44,12 @@ from typing import (
|
|
|
44
44
|
Optional,
|
|
45
45
|
Tuple,
|
|
46
46
|
TYPE_CHECKING,
|
|
47
|
+
TypedDict,
|
|
47
48
|
)
|
|
48
49
|
|
|
49
50
|
import torchx
|
|
50
51
|
import yaml
|
|
51
52
|
from torchx.schedulers.api import (
|
|
52
|
-
AppDryRunInfo,
|
|
53
53
|
DescribeAppResponse,
|
|
54
54
|
filter_regex,
|
|
55
55
|
ListAppResponse,
|
|
@@ -60,6 +60,7 @@ from torchx.schedulers.api import (
|
|
|
60
60
|
from torchx.schedulers.ids import make_unique
|
|
61
61
|
from torchx.specs.api import (
|
|
62
62
|
AppDef,
|
|
63
|
+
AppDryRunInfo,
|
|
63
64
|
AppState,
|
|
64
65
|
BindMount,
|
|
65
66
|
CfgVal,
|
|
@@ -75,7 +76,6 @@ from torchx.specs.api import (
|
|
|
75
76
|
)
|
|
76
77
|
from torchx.util.strings import normalize_str
|
|
77
78
|
from torchx.workspace.docker_workspace import DockerWorkspaceMixin
|
|
78
|
-
from typing_extensions import TypedDict
|
|
79
79
|
|
|
80
80
|
|
|
81
81
|
if TYPE_CHECKING:
|
|
@@ -40,10 +40,10 @@ from typing import (
|
|
|
40
40
|
Protocol,
|
|
41
41
|
TextIO,
|
|
42
42
|
Tuple,
|
|
43
|
+
TypedDict,
|
|
43
44
|
)
|
|
44
45
|
|
|
45
46
|
from torchx.schedulers.api import (
|
|
46
|
-
AppDryRunInfo,
|
|
47
47
|
DescribeAppResponse,
|
|
48
48
|
filter_regex,
|
|
49
49
|
ListAppResponse,
|
|
@@ -53,10 +53,10 @@ from torchx.schedulers.api import (
|
|
|
53
53
|
)
|
|
54
54
|
from torchx.schedulers.ids import make_unique
|
|
55
55
|
from torchx.schedulers.streams import Tee
|
|
56
|
+
from torchx.specs import AppDryRunInfo
|
|
56
57
|
from torchx.specs.api import AppDef, AppState, is_terminal, macros, NONE, Role, runopts
|
|
57
58
|
|
|
58
59
|
from torchx.util.types import none_throws
|
|
59
|
-
from typing_extensions import TypedDict
|
|
60
60
|
|
|
61
61
|
log: logging.Logger = logging.getLogger(__name__)
|
|
62
62
|
|
|
@@ -29,11 +29,10 @@ import subprocess
|
|
|
29
29
|
import tempfile
|
|
30
30
|
from dataclasses import dataclass
|
|
31
31
|
from datetime import datetime
|
|
32
|
-
from typing import Any, Dict, Iterable, List, Optional
|
|
32
|
+
from typing import Any, Dict, Iterable, List, Optional, TypedDict
|
|
33
33
|
|
|
34
34
|
import torchx
|
|
35
35
|
from torchx.schedulers.api import (
|
|
36
|
-
AppDryRunInfo,
|
|
37
36
|
DescribeAppResponse,
|
|
38
37
|
filter_regex,
|
|
39
38
|
ListAppResponse,
|
|
@@ -45,6 +44,7 @@ from torchx.schedulers.ids import make_unique
|
|
|
45
44
|
from torchx.schedulers.local_scheduler import LogIterator
|
|
46
45
|
from torchx.specs import (
|
|
47
46
|
AppDef,
|
|
47
|
+
AppDryRunInfo,
|
|
48
48
|
AppState,
|
|
49
49
|
BindMount,
|
|
50
50
|
DeviceMount,
|
|
@@ -57,7 +57,6 @@ from torchx.specs import (
|
|
|
57
57
|
VolumeMount,
|
|
58
58
|
)
|
|
59
59
|
from torchx.util import shlex
|
|
60
|
-
from typing_extensions import TypedDict
|
|
61
60
|
|
|
62
61
|
JOB_STATE: Dict[str, AppState] = {
|
|
63
62
|
"DONE": AppState.SUCCEEDED,
|
|
@@ -14,7 +14,17 @@ import time
|
|
|
14
14
|
from dataclasses import dataclass, field
|
|
15
15
|
from datetime import datetime
|
|
16
16
|
from shutil import copy2, rmtree
|
|
17
|
-
from typing import
|
|
17
|
+
from typing import ( # noqa
|
|
18
|
+
Any,
|
|
19
|
+
cast,
|
|
20
|
+
Dict,
|
|
21
|
+
Final,
|
|
22
|
+
Iterable,
|
|
23
|
+
List,
|
|
24
|
+
Optional,
|
|
25
|
+
Tuple,
|
|
26
|
+
TypedDict,
|
|
27
|
+
)
|
|
18
28
|
|
|
19
29
|
import urllib3
|
|
20
30
|
|
|
@@ -23,7 +33,6 @@ from ray.dashboard.modules.job.common import JobStatus
|
|
|
23
33
|
from ray.dashboard.modules.job.sdk import JobSubmissionClient
|
|
24
34
|
|
|
25
35
|
from torchx.schedulers.api import (
|
|
26
|
-
AppDryRunInfo,
|
|
27
36
|
AppState,
|
|
28
37
|
DescribeAppResponse,
|
|
29
38
|
filter_regex,
|
|
@@ -34,9 +43,17 @@ from torchx.schedulers.api import (
|
|
|
34
43
|
)
|
|
35
44
|
from torchx.schedulers.ids import make_unique
|
|
36
45
|
from torchx.schedulers.ray.ray_common import RayActor, TORCHX_RANK0_HOST
|
|
37
|
-
from torchx.specs import
|
|
46
|
+
from torchx.specs import (
|
|
47
|
+
AppDef,
|
|
48
|
+
AppDryRunInfo,
|
|
49
|
+
macros,
|
|
50
|
+
NONE,
|
|
51
|
+
ReplicaStatus,
|
|
52
|
+
Role,
|
|
53
|
+
RoleStatus,
|
|
54
|
+
runopts,
|
|
55
|
+
)
|
|
38
56
|
from torchx.workspace.dir_workspace import TmpDirWorkspaceMixin
|
|
39
|
-
from typing_extensions import TypedDict
|
|
40
57
|
|
|
41
58
|
|
|
42
59
|
class RayOpts(TypedDict, total=False):
|
|
@@ -21,11 +21,10 @@ import tempfile
|
|
|
21
21
|
from dataclasses import dataclass
|
|
22
22
|
from datetime import datetime
|
|
23
23
|
from subprocess import CalledProcessError, PIPE
|
|
24
|
-
from typing import Any, Dict, Iterable, List, Mapping, Optional, Tuple
|
|
24
|
+
from typing import Any, Dict, Iterable, List, Mapping, Optional, Tuple, TypedDict
|
|
25
25
|
|
|
26
26
|
import torchx
|
|
27
27
|
from torchx.schedulers.api import (
|
|
28
|
-
AppDryRunInfo,
|
|
29
28
|
DescribeAppResponse,
|
|
30
29
|
filter_regex,
|
|
31
30
|
ListAppResponse,
|
|
@@ -36,6 +35,7 @@ from torchx.schedulers.api import (
|
|
|
36
35
|
from torchx.schedulers.local_scheduler import LogIterator
|
|
37
36
|
from torchx.specs import (
|
|
38
37
|
AppDef,
|
|
38
|
+
AppDryRunInfo,
|
|
39
39
|
AppState,
|
|
40
40
|
macros,
|
|
41
41
|
NONE,
|
|
@@ -46,7 +46,6 @@ from torchx.specs import (
|
|
|
46
46
|
runopts,
|
|
47
47
|
)
|
|
48
48
|
from torchx.workspace.dir_workspace import DirWorkspaceMixin
|
|
49
|
-
from typing_extensions import TypedDict
|
|
50
49
|
|
|
51
50
|
SLURM_JOB_DIRS = ".torchxslurmjobdirs"
|
|
52
51
|
|
torchx/util/entrypoints.py
CHANGED
|
@@ -5,14 +5,13 @@
|
|
|
5
5
|
# LICENSE file in the root directory of this source tree.
|
|
6
6
|
|
|
7
7
|
# pyre-strict
|
|
8
|
+
# pyre-ignore-all-errors[3, 2, 16]
|
|
8
9
|
|
|
10
|
+
from importlib import metadata
|
|
11
|
+
from importlib.metadata import EntryPoint
|
|
9
12
|
from typing import Any, Dict, Optional
|
|
10
13
|
|
|
11
|
-
import importlib_metadata as metadata
|
|
12
|
-
from importlib_metadata import EntryPoint
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
# pyre-ignore-all-errors[3, 2]
|
|
16
15
|
def load(group: str, name: str, default=None):
|
|
17
16
|
"""
|
|
18
17
|
Loads the entry point specified by
|
|
@@ -30,13 +29,34 @@ def load(group: str, name: str, default=None):
|
|
|
30
29
|
raises an error.
|
|
31
30
|
"""
|
|
32
31
|
|
|
33
|
-
|
|
32
|
+
# [note_on_entrypoints]
|
|
33
|
+
# return type of importlib.metadata.entry_points() is different between python-3.9 and python-3.10
|
|
34
|
+
# https://docs.python.org/3.9/library/importlib.metadata.html#importlib.metadata.entry_points
|
|
35
|
+
# https://docs.python.org/3.10/library/importlib.metadata.html#importlib.metadata.entry_points
|
|
36
|
+
if hasattr(metadata.entry_points(), "select"):
|
|
37
|
+
# python>=3.10
|
|
38
|
+
entrypoints = metadata.entry_points().select(group=group)
|
|
34
39
|
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
if name not in entrypoints.names and default is not None:
|
|
41
|
+
return default
|
|
42
|
+
|
|
43
|
+
ep = entrypoints[name]
|
|
44
|
+
return ep.load()
|
|
37
45
|
|
|
38
|
-
|
|
39
|
-
|
|
46
|
+
else:
|
|
47
|
+
# python<3.10 (e.g. 3.9)
|
|
48
|
+
# metadata.entry_points() returns dict[str, tuple[EntryPoint]] (not EntryPoints) in python-3.9
|
|
49
|
+
entrypoints = metadata.entry_points().get(group, ())
|
|
50
|
+
|
|
51
|
+
for ep in entrypoints:
|
|
52
|
+
if ep.name == name:
|
|
53
|
+
return ep.load()
|
|
54
|
+
|
|
55
|
+
# [group].name not found
|
|
56
|
+
if default is not None:
|
|
57
|
+
return default
|
|
58
|
+
else:
|
|
59
|
+
raise KeyError(f"entrypoint {group}.{name} not found")
|
|
40
60
|
|
|
41
61
|
|
|
42
62
|
def _defer_load_ep(ep: EntryPoint) -> object:
|
|
@@ -49,7 +69,6 @@ def _defer_load_ep(ep: EntryPoint) -> object:
|
|
|
49
69
|
return run
|
|
50
70
|
|
|
51
71
|
|
|
52
|
-
# pyre-ignore-all-errors[3, 2]
|
|
53
72
|
def load_group(
|
|
54
73
|
group: str, default: Optional[Dict[str, Any]] = None, skip_defaults: bool = False
|
|
55
74
|
):
|
|
@@ -87,7 +106,13 @@ def load_group(
|
|
|
87
106
|
|
|
88
107
|
"""
|
|
89
108
|
|
|
90
|
-
|
|
109
|
+
# see [note_on_entrypoints] above
|
|
110
|
+
if hasattr(metadata.entry_points(), "select"):
|
|
111
|
+
# python>=3.10
|
|
112
|
+
entrypoints = metadata.entry_points().select(group=group)
|
|
113
|
+
else:
|
|
114
|
+
# python<3.10 (e.g. 3.9)
|
|
115
|
+
entrypoints = metadata.entry_points().get(group, ())
|
|
91
116
|
|
|
92
117
|
if len(entrypoints) == 0:
|
|
93
118
|
if skip_defaults:
|
torchx/util/types.py
CHANGED
|
@@ -8,12 +8,10 @@
|
|
|
8
8
|
|
|
9
9
|
import inspect
|
|
10
10
|
import re
|
|
11
|
-
from typing import Any, Callable,
|
|
11
|
+
from typing import Any, Callable, Optional, Tuple, TypeVar, Union
|
|
12
12
|
|
|
13
|
-
import typing_inspect
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
def to_list(arg: str) -> List[str]:
|
|
14
|
+
def to_list(arg: str) -> list[str]:
|
|
17
15
|
conf = []
|
|
18
16
|
if len(arg.strip()) == 0:
|
|
19
17
|
return []
|
|
@@ -22,9 +20,9 @@ def to_list(arg: str) -> List[str]:
|
|
|
22
20
|
return conf
|
|
23
21
|
|
|
24
22
|
|
|
25
|
-
def to_dict(arg: str) ->
|
|
23
|
+
def to_dict(arg: str) -> dict[str, str]:
|
|
26
24
|
"""
|
|
27
|
-
Parses the given ``arg`` string literal into a ``
|
|
25
|
+
Parses the given ``arg`` string literal into a ``dict[str, str]`` of
|
|
28
26
|
key-value pairs delimited by ``"="`` (equals). The values may be a
|
|
29
27
|
list literal where the list elements are delimited by ``","`` (comma)
|
|
30
28
|
or ``";"`` (semi-colon). The same delimiters (``","`` and ``";"``) are used
|
|
@@ -85,14 +83,14 @@ def to_dict(arg: str) -> Dict[str, str]:
|
|
|
85
83
|
return val[1:-1]
|
|
86
84
|
return val if val != '""' and val != "''" else ""
|
|
87
85
|
|
|
88
|
-
arg_map:
|
|
86
|
+
arg_map: dict[str, str] = {}
|
|
89
87
|
|
|
90
88
|
if not arg:
|
|
91
89
|
return arg_map
|
|
92
90
|
|
|
93
91
|
# find quoted values
|
|
94
92
|
quoted_pattern = r'([\'"])((?:\\.|(?!\1).)*?)\1'
|
|
95
|
-
quoted_values:
|
|
93
|
+
quoted_values: list[str] = []
|
|
96
94
|
|
|
97
95
|
def replace_quoted(match):
|
|
98
96
|
quoted_values.append(match.group(0))
|
|
@@ -133,9 +131,13 @@ def to_dict(arg: str) -> Dict[str, str]:
|
|
|
133
131
|
|
|
134
132
|
# pyre-ignore-all-errors[3, 2]
|
|
135
133
|
def _decode_string_to_dict(
|
|
136
|
-
encoded_value: str, param_type:
|
|
137
|
-
) ->
|
|
138
|
-
|
|
134
|
+
encoded_value: str, param_type: type[dict[Any, Any]]
|
|
135
|
+
) -> dict[Any, Any]:
|
|
136
|
+
# pyre-ignore[16]
|
|
137
|
+
if not hasattr(param_type, "__args__") or len(param_type.__args__) != 2:
|
|
138
|
+
raise ValueError(f"param_type must be a `dict` type, but was `{param_type}`")
|
|
139
|
+
|
|
140
|
+
key_type, value_type = param_type.__args__
|
|
139
141
|
arg_values = {}
|
|
140
142
|
for key, value in to_dict(encoded_value).items():
|
|
141
143
|
arg_values[key_type(key)] = value_type(value)
|
|
@@ -143,9 +145,12 @@ def _decode_string_to_dict(
|
|
|
143
145
|
|
|
144
146
|
|
|
145
147
|
def _decode_string_to_list(
|
|
146
|
-
encoded_value: str, param_type:
|
|
147
|
-
) ->
|
|
148
|
-
|
|
148
|
+
encoded_value: str, param_type: type[list[Any]]
|
|
149
|
+
) -> list[Any]:
|
|
150
|
+
# pyre-ignore[16]
|
|
151
|
+
if not hasattr(param_type, "__args__") or len(param_type.__args__) != 1:
|
|
152
|
+
raise ValueError(f"param_type must be a `list` type, but was `{param_type}`")
|
|
153
|
+
value_type = param_type.__args__[0]
|
|
149
154
|
if not is_primitive(value_type):
|
|
150
155
|
raise ValueError("List types support only primitives: int, str, float")
|
|
151
156
|
arg_values = []
|
|
@@ -166,7 +171,7 @@ def decode(encoded_value: Any, annotation: Any):
|
|
|
166
171
|
|
|
167
172
|
def decode_from_string(
|
|
168
173
|
encoded_value: str, annotation: Any
|
|
169
|
-
) -> Union[
|
|
174
|
+
) -> Union[dict[Any, Any], list[Any], None]:
|
|
170
175
|
"""Decodes string representation to the underlying type(Dict or List)
|
|
171
176
|
|
|
172
177
|
Given a string representation of the value, the method decodes it according
|
|
@@ -191,13 +196,13 @@ def decode_from_string(
|
|
|
191
196
|
if not encoded_value:
|
|
192
197
|
return None
|
|
193
198
|
value_type = annotation
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
199
|
+
if hasattr(value_type, "__origin__"):
|
|
200
|
+
value_origin = value_type.__origin__
|
|
201
|
+
if value_origin is dict:
|
|
202
|
+
return _decode_string_to_dict(encoded_value, value_type)
|
|
203
|
+
elif value_origin is list:
|
|
204
|
+
return _decode_string_to_list(encoded_value, value_type)
|
|
205
|
+
raise ValueError("Unknown")
|
|
201
206
|
|
|
202
207
|
|
|
203
208
|
def is_bool(param_type: Any) -> bool:
|
|
@@ -229,12 +234,13 @@ def decode_optional(param_type: Any) -> Any:
|
|
|
229
234
|
If ``param_type`` is type Optional[INNER_TYPE], method returns INNER_TYPE
|
|
230
235
|
Otherwise returns ``param_type``
|
|
231
236
|
"""
|
|
232
|
-
|
|
233
|
-
|
|
237
|
+
if not hasattr(param_type, "__origin__"):
|
|
238
|
+
return param_type
|
|
239
|
+
if param_type.__origin__ is not Union:
|
|
234
240
|
return param_type
|
|
235
|
-
|
|
236
|
-
if
|
|
237
|
-
return
|
|
241
|
+
args = param_type.__args__
|
|
242
|
+
if len(args) == 2 and args[1] is type(None):
|
|
243
|
+
return args[0]
|
|
238
244
|
else:
|
|
239
245
|
return param_type
|
|
240
246
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: torchx-nightly
|
|
3
|
-
Version: 2025.7.
|
|
3
|
+
Version: 2025.7.4
|
|
4
4
|
Summary: TorchX SDK and Components
|
|
5
5
|
Home-page: https://github.com/pytorch/torchx
|
|
6
6
|
Author: TorchX Devs
|
|
@@ -17,9 +17,7 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
|
17
17
|
Requires-Python: >=3.7
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
License-File: LICENSE
|
|
20
|
-
Requires-Dist: pyre-extensions
|
|
21
20
|
Requires-Dist: docstring-parser>=0.8.1
|
|
22
|
-
Requires-Dist: importlib-metadata
|
|
23
21
|
Requires-Dist: pyyaml
|
|
24
22
|
Requires-Dist: docker
|
|
25
23
|
Requires-Dist: filelock
|
|
@@ -60,6 +58,7 @@ Requires-Dist: torchmetrics==1.6.3; extra == "dev"
|
|
|
60
58
|
Requires-Dist: torchserve>=0.10.0; extra == "dev"
|
|
61
59
|
Requires-Dist: torchtext==0.18.0; extra == "dev"
|
|
62
60
|
Requires-Dist: torchvision==0.22.0; extra == "dev"
|
|
61
|
+
Requires-Dist: typing-extensions; extra == "dev"
|
|
63
62
|
Requires-Dist: ts==0.5.1; extra == "dev"
|
|
64
63
|
Requires-Dist: ray[default]; extra == "dev"
|
|
65
64
|
Requires-Dist: wheel; extra == "dev"
|
|
@@ -28,7 +28,7 @@ torchx/components/dist.py,sha256=9jECk3jjQ4Yh4oWDK8vnQ7kcI0-OWCbbwj8uvBdI9FU,145
|
|
|
28
28
|
torchx/components/interpret.py,sha256=g8gkKdDJvsBfX1ZrpVT7n2bMEtmwRV_1AqDyAnnQ_aA,697
|
|
29
29
|
torchx/components/metrics.py,sha256=1gbp8BfzZWGa7PD1db5vRADlONzmae4qSBUUdCWayr0,2814
|
|
30
30
|
torchx/components/serve.py,sha256=uxIC5gU2ecg0EJIPX_oEPzNNOXRAre4j2eXusrgwGAI,2156
|
|
31
|
-
torchx/components/structured_arg.py,sha256=
|
|
31
|
+
torchx/components/structured_arg.py,sha256=8jMcd0rtUmzCKEQKJ_JYzxSkMMK9q0fYjkwAs6wo78E,9595
|
|
32
32
|
torchx/components/train.py,sha256=vtrQXRcD7bIcbb3lSeyD9BBlIe1mv1WNW6rnLK9R0Mw,1259
|
|
33
33
|
torchx/components/utils.py,sha256=QRBxBm1OnNhOhpPs0lKdbJ8_mNhWYMklY6cl1gPIw9A,9363
|
|
34
34
|
torchx/components/integration_tests/__init__.py,sha256=Md3cCHD7Ano9kV15PqGbicgUO-RMdh4aVy1yKiDt_xE,208
|
|
@@ -56,7 +56,7 @@ torchx/pipelines/kfp/__init__.py,sha256=8iJ8lql_fxwuk9VCYSxXnX6tPL228fB5mDZpOs-k
|
|
|
56
56
|
torchx/pipelines/kfp/adapter.py,sha256=5GeHULjb1kxG6wJtYVLpNkgdzUi4iYEaR42VFOwT6fY,9045
|
|
57
57
|
torchx/pipelines/kfp/version.py,sha256=mYBxd6bm4MeR34D--xo-JLQ9wHeAl_ZQLwbItCf9tr0,539
|
|
58
58
|
torchx/runner/__init__.py,sha256=x8Sz7s_tLxPgJgvWIhK4ju9BNZU61uBFywGwDY6CqJs,315
|
|
59
|
-
torchx/runner/api.py,sha256=
|
|
59
|
+
torchx/runner/api.py,sha256=SQPwc_gar6o1qCBfjvG3XS4tQ6qcsNwUPuQTjJ6thXM,30085
|
|
60
60
|
torchx/runner/config.py,sha256=qpq_RfUSUykquAsEKOhDT3xBsa-m3wc6F6O8oP2QJ7k,18303
|
|
61
61
|
torchx/runner/events/__init__.py,sha256=1_y0bojXl3FL0zlAj7BI4Dg5cXKXUmaa2jZbVH0EDUA,5268
|
|
62
62
|
torchx/runner/events/api.py,sha256=pPLfowWTXtN_XcrEDNI45pE6Ijvdc_Gdxq76RduqgGE,2664
|
|
@@ -64,20 +64,20 @@ torchx/runner/events/handlers.py,sha256=ThHCIJW21BfBgB7b6ftyjASJmD1KdizpjuTtsyqn
|
|
|
64
64
|
torchx/runtime/__init__.py,sha256=Wxje2BryzeQneFu5r6P9JJiEKG-_C9W1CcZ_JNrKT6g,593
|
|
65
65
|
torchx/runtime/tracking/__init__.py,sha256=dYnAPnrXYREfPXkpHhdOFkcYIODWEbA13PdD-wLQYBo,3055
|
|
66
66
|
torchx/runtime/tracking/api.py,sha256=SmUQyUKZqG3KlAhT7CJOGqRz1O274E4m63wQeOVq3CU,5472
|
|
67
|
-
torchx/schedulers/__init__.py,sha256=
|
|
68
|
-
torchx/schedulers/api.py,sha256=
|
|
69
|
-
torchx/schedulers/aws_batch_scheduler.py,sha256=
|
|
70
|
-
torchx/schedulers/aws_sagemaker_scheduler.py,sha256=
|
|
67
|
+
torchx/schedulers/__init__.py,sha256=igIBdxGhkuzH7oYVFXIA9xwjkSn3QzWZ_9dhfdl_M0I,2299
|
|
68
|
+
torchx/schedulers/api.py,sha256=FbyG7mNnbXXj2_W1dQ_MnNO6fQe2FAd1rEz1R-BNg-c,14598
|
|
69
|
+
torchx/schedulers/aws_batch_scheduler.py,sha256=06CpJw6Y71-g9CH6A6lul5-WLO5qxINf3UKLyyNmzS0,28105
|
|
70
|
+
torchx/schedulers/aws_sagemaker_scheduler.py,sha256=flN8GumKE2Dz4X_foAt6Jnvt-ZVojWs6pcyrHwB0hz0,20921
|
|
71
71
|
torchx/schedulers/devices.py,sha256=RjVcu22ZRl_9OKtOtmA1A3vNXgu2qD6A9ST0L0Hsg4I,1734
|
|
72
|
-
torchx/schedulers/docker_scheduler.py,sha256=
|
|
73
|
-
torchx/schedulers/gcp_batch_scheduler.py,sha256=
|
|
72
|
+
torchx/schedulers/docker_scheduler.py,sha256=xuK00-dB6o8TV1YaZox7O5P09LHB2KeQ6t4eiNtqMYQ,16781
|
|
73
|
+
torchx/schedulers/gcp_batch_scheduler.py,sha256=JQuaEJVL_7NSa9AeUc_0Qo74XZNJk_kp6XwgunvlUKI,16281
|
|
74
74
|
torchx/schedulers/ids.py,sha256=3E-_vwVYC-8Tv8kjuY9-W7TbOe_-Laqd8a65uIN3hQY,1798
|
|
75
|
-
torchx/schedulers/kubernetes_mcad_scheduler.py,sha256
|
|
76
|
-
torchx/schedulers/kubernetes_scheduler.py,sha256=
|
|
77
|
-
torchx/schedulers/local_scheduler.py,sha256=
|
|
78
|
-
torchx/schedulers/lsf_scheduler.py,sha256=
|
|
79
|
-
torchx/schedulers/ray_scheduler.py,sha256=
|
|
80
|
-
torchx/schedulers/slurm_scheduler.py,sha256=
|
|
75
|
+
torchx/schedulers/kubernetes_mcad_scheduler.py,sha256=1tuzq3OutCMdSPqg_dNmCHt_wyuSFKG0-ywLc3qITJo,42949
|
|
76
|
+
torchx/schedulers/kubernetes_scheduler.py,sha256=0_loGJ7WnxEr9dhgFt3Gw-7nVLirMDVN-MAFTCq7erE,28217
|
|
77
|
+
torchx/schedulers/local_scheduler.py,sha256=lOtVtmMIhytdju1Dlc3p99VALMY3qYRDPqjxdyTAbQQ,41877
|
|
78
|
+
torchx/schedulers/lsf_scheduler.py,sha256=YS6Yel8tXJqLPxbcGz95lZG2nCi36AQXdNDyuBJePKg,17661
|
|
79
|
+
torchx/schedulers/ray_scheduler.py,sha256=T-jsGSOa8O-h1kTUU7Q7Fk1RILL1Yzvuos_WFSQF8Fo,15795
|
|
80
|
+
torchx/schedulers/slurm_scheduler.py,sha256=zM_9XYVm7sQ8NGN-N26D-2YIfE83JS3mvpPb40CDKcA,26411
|
|
81
81
|
torchx/schedulers/streams.py,sha256=8_SLezgnWgfv_zXUsJCUM34-h2dtv25NmZuxEwkzmxw,2007
|
|
82
82
|
torchx/schedulers/ray/__init__.py,sha256=fE0IHi1JJpxsNVBNzWNee2thrNXFFRhY94c80RxNSIE,231
|
|
83
83
|
torchx/schedulers/ray/ray_common.py,sha256=pyNYFvTKVwdjDAeCBNbPwAWwVNmlLOJWExfn90XY8u8,610
|
|
@@ -103,21 +103,21 @@ torchx/tracker/backend/fsspec.py,sha256=528xKryBE27Rm_OHD7r2R6fmVAclknBtoy1s034N
|
|
|
103
103
|
torchx/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
104
104
|
torchx/util/cuda.py,sha256=-ZTa1WCLnY2WtSWAdWufLQqZSDCZfZsloBuiS84LIkU,1099
|
|
105
105
|
torchx/util/datetime.py,sha256=hV6Sg0u5KTBe68yrmy_RGCC5su0i4Tb_mAYphWamiXI,405
|
|
106
|
-
torchx/util/entrypoints.py,sha256=
|
|
106
|
+
torchx/util/entrypoints.py,sha256=XgwCjQ5f1xchUVxABiPqODgd3--SrOtUTlgtMlAeKKc,3980
|
|
107
107
|
torchx/util/io.py,sha256=HNpWLcFUX0WTAP3CsdamHz--FR5A4kSdLCPfNqa2UkA,1807
|
|
108
108
|
torchx/util/log_tee_helpers.py,sha256=wPyozmh9BOt_2d3Gxa0iNogwnjzwFitIIMBJOJ1arIw,6330
|
|
109
109
|
torchx/util/modules.py,sha256=o4y_d07gTpJ4nIVBcoUVJ0JtXIHEsEC5kbgBM6NGpgA,2135
|
|
110
110
|
torchx/util/session.py,sha256=r6M_nyzXgcbk1GgYGZ324F_ehRGCqjjdVk4YgKxMj8M,1214
|
|
111
111
|
torchx/util/shlex.py,sha256=eXEKu8KC3zIcd8tEy9_s8Ds5oma8BORr-0VGWNpG2dk,463
|
|
112
112
|
torchx/util/strings.py,sha256=GkLWCmYS89Uv6bWc5hH0XwvHy7oQmprv2U7axC4A2e8,678
|
|
113
|
-
torchx/util/types.py,sha256=
|
|
113
|
+
torchx/util/types.py,sha256=xelu9gOUQ540GvvzDqk1wYb4csB09OgYQJwlVz62O5o,8889
|
|
114
114
|
torchx/workspace/__init__.py,sha256=FqN8AN4VhR1C_SBY10MggQvNZmyanbbuPuE-JCjkyUY,798
|
|
115
115
|
torchx/workspace/api.py,sha256=PtDkGTC5lX03pRoYpuMz2KCmM1ZOycRP1UknqvNb97Y,6341
|
|
116
116
|
torchx/workspace/dir_workspace.py,sha256=npNW_IjUZm_yS5r-8hrRkH46ndDd9a_eApT64m1S1T4,2268
|
|
117
117
|
torchx/workspace/docker_workspace.py,sha256=PFu2KQNVC-0p2aKJ-W_BKA9ZOmXdCY2ABEkCExp3udQ,10269
|
|
118
|
-
torchx_nightly-2025.7.
|
|
119
|
-
torchx_nightly-2025.7.
|
|
120
|
-
torchx_nightly-2025.7.
|
|
121
|
-
torchx_nightly-2025.7.
|
|
122
|
-
torchx_nightly-2025.7.
|
|
123
|
-
torchx_nightly-2025.7.
|
|
118
|
+
torchx_nightly-2025.7.4.dist-info/LICENSE,sha256=WVHfXhFC0Ia8LTKt_nJVYobdqTJVg_4J3Crrfm2A8KQ,1721
|
|
119
|
+
torchx_nightly-2025.7.4.dist-info/METADATA,sha256=qx4GgZmM9wnMVd73lF0JKOYxltK4x20PCAueLnrp1Hg,6103
|
|
120
|
+
torchx_nightly-2025.7.4.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
|
121
|
+
torchx_nightly-2025.7.4.dist-info/entry_points.txt,sha256=T328AMXeKI3JZnnxfkEew2ZcMN1oQDtkXjMz7lkV-P4,169
|
|
122
|
+
torchx_nightly-2025.7.4.dist-info/top_level.txt,sha256=pxew3bc2gsiViS0zADs0jb6kC5v8o_Yy_85fhHj_J1A,7
|
|
123
|
+
torchx_nightly-2025.7.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|