groundhog-hpc 0.5.5__tar.gz → 0.5.6__tar.gz
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.
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/PKG-INFO +1 -1
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/app/run.py +3 -2
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/compute.py +7 -7
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/configuration/models.py +0 -3
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/configuration/pep723.py +1 -1
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/decorators.py +7 -10
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/function.py +10 -17
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/templates/init_script.py.jinja +1 -2
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/.gitignore +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/LICENSE +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/README.md +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/pyproject.toml +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/__init__.py +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/app/__init__.py +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/app/add.py +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/app/init.py +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/app/main.py +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/app/remove.py +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/app/utils.py +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/configuration/__init__.py +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/configuration/defaults.py +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/configuration/endpoints.py +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/configuration/resolver.py +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/console.py +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/errors.py +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/future.py +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/harness.py +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/import_hook.py +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/serialization.py +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/templates/groundhog_run.py.jinja +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/templates/shell_command.sh.jinja +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/templating.py +0 -0
- {groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/utils.py +0 -0
|
@@ -92,8 +92,9 @@ def run(
|
|
|
92
92
|
except RemoteExecutionError as e:
|
|
93
93
|
if e.returncode == 124:
|
|
94
94
|
typer.echo(
|
|
95
|
-
"Remote execution failed (timed out
|
|
96
|
-
"
|
|
95
|
+
"Remote execution failed: (exit code 124 - timed out). \nTry increasing walltime for "
|
|
96
|
+
"long running jobs by setting my_function.walltime (in seconds) "
|
|
97
|
+
"before invoking my_function.remote/submit()",
|
|
97
98
|
err=True,
|
|
98
99
|
)
|
|
99
100
|
raise
|
|
@@ -44,7 +44,10 @@ def _get_compute_client() -> Client:
|
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
def script_to_submittable(
|
|
47
|
-
script_path: str,
|
|
47
|
+
script_path: str,
|
|
48
|
+
function_name: str,
|
|
49
|
+
payload: str,
|
|
50
|
+
walltime: int | float | None = None,
|
|
48
51
|
) -> ShellFunction:
|
|
49
52
|
"""Convert a user script and function name into a Globus Compute ShellFunction.
|
|
50
53
|
|
|
@@ -52,6 +55,7 @@ def script_to_submittable(
|
|
|
52
55
|
script_path: Path to the Python script containing the function
|
|
53
56
|
function_name: Name of the function to execute remotely
|
|
54
57
|
payload: Serialized arguments string
|
|
58
|
+
walltime: Optional maximum execution time in seconds for ShellFunction timeout
|
|
55
59
|
|
|
56
60
|
Returns:
|
|
57
61
|
A ShellFunction ready to be submitted to a Globus Compute executor
|
|
@@ -60,7 +64,7 @@ def script_to_submittable(
|
|
|
60
64
|
|
|
61
65
|
shell_command = template_shell_command(script_path, function_name, payload)
|
|
62
66
|
shell_function = gc.ShellFunction(
|
|
63
|
-
shell_command, name=function_name.replace(".", "_")
|
|
67
|
+
shell_command, name=function_name.replace(".", "_"), walltime=walltime
|
|
64
68
|
)
|
|
65
69
|
return shell_function
|
|
66
70
|
|
|
@@ -82,12 +86,8 @@ def submit_to_executor(
|
|
|
82
86
|
"""
|
|
83
87
|
import globus_compute_sdk as gc
|
|
84
88
|
|
|
85
|
-
# Extract walltime and set it on the shell function
|
|
86
|
-
config = user_endpoint_config.copy()
|
|
87
|
-
if "walltime" in config:
|
|
88
|
-
shell_function.walltime = config.pop("walltime")
|
|
89
|
-
|
|
90
89
|
# Validate config against endpoint schema and filter out unexpected keys
|
|
90
|
+
config = user_endpoint_config.copy()
|
|
91
91
|
if schema := get_endpoint_schema(endpoint):
|
|
92
92
|
expected_keys = set(schema.get("properties", {}).keys())
|
|
93
93
|
unexpected_keys = set(config.keys()) - expected_keys
|
|
@@ -24,12 +24,10 @@ class EndpointConfig(BaseModel, extra="allow"):
|
|
|
24
24
|
|
|
25
25
|
Attributes:
|
|
26
26
|
endpoint: Globus Compute endpoint UUID (required for base configs)
|
|
27
|
-
walltime: Maximum execution time in seconds (must be positive)
|
|
28
27
|
worker_init: Shell commands to run in worker initialization
|
|
29
28
|
"""
|
|
30
29
|
|
|
31
30
|
endpoint: str | UUID
|
|
32
|
-
walltime: int | None = Field(None, gt=0)
|
|
33
31
|
worker_init: str | None = None
|
|
34
32
|
|
|
35
33
|
|
|
@@ -50,7 +48,6 @@ class EndpointVariant(BaseModel, extra="allow"):
|
|
|
50
48
|
"""
|
|
51
49
|
|
|
52
50
|
endpoint: None = None
|
|
53
|
-
walltime: int | None = Field(None, gt=0)
|
|
54
51
|
worker_init: str | None = None
|
|
55
52
|
|
|
56
53
|
@model_validator(mode="before")
|
|
@@ -39,7 +39,7 @@ def read_pep723(script: str) -> Pep723Metadata | None:
|
|
|
39
39
|
|
|
40
40
|
Raises:
|
|
41
41
|
ValueError: If multiple 'script' metadata blocks are found
|
|
42
|
-
ValidationError: If metadata contains invalid configuration
|
|
42
|
+
ValidationError: If metadata contains invalid configuration
|
|
43
43
|
"""
|
|
44
44
|
name = "script"
|
|
45
45
|
matches = list(
|
|
@@ -45,7 +45,6 @@ def harness() -> Callable[[FunctionType], Harness]:
|
|
|
45
45
|
|
|
46
46
|
def function(
|
|
47
47
|
endpoint: str | None = None,
|
|
48
|
-
walltime: int | None = None,
|
|
49
48
|
**user_endpoint_config: Any,
|
|
50
49
|
) -> Callable[[FunctionType], Function]:
|
|
51
50
|
"""Decorator to mark a function for remote execution on Globus Compute.
|
|
@@ -56,17 +55,17 @@ def function(
|
|
|
56
55
|
- Submitted asynchronously: func.submit(args)
|
|
57
56
|
|
|
58
57
|
Args:
|
|
59
|
-
endpoint: Globus Compute endpoint UUID
|
|
60
|
-
|
|
58
|
+
endpoint: Globus Compute endpoint UUID or named endpoint from
|
|
59
|
+
`[tool.hog.<name>]` PEP 723 metadata
|
|
61
60
|
**user_endpoint_config: Options to pass through to the Executor as
|
|
62
|
-
user_endpoint_config (e.g. account, partition, etc)
|
|
61
|
+
user_endpoint_config (e.g. account, partition, walltime, etc)
|
|
63
62
|
|
|
64
63
|
Returns:
|
|
65
64
|
A decorator function that wraps the function as a Function instance
|
|
66
65
|
|
|
67
66
|
Example:
|
|
68
67
|
```python
|
|
69
|
-
@hog.function(endpoint="my-remote-endpoint-uuid",
|
|
68
|
+
@hog.function(endpoint="my-remote-endpoint-uuid", account='my-account')
|
|
70
69
|
def train_model(data):
|
|
71
70
|
# This runs on the remote HPC cluster
|
|
72
71
|
model = train(data)
|
|
@@ -81,7 +80,7 @@ def function(
|
|
|
81
80
|
"""
|
|
82
81
|
|
|
83
82
|
def decorator(func: FunctionType) -> Function:
|
|
84
|
-
wrapper = Function(func, endpoint,
|
|
83
|
+
wrapper = Function(func, endpoint, **user_endpoint_config)
|
|
85
84
|
functools.update_wrapper(wrapper, func)
|
|
86
85
|
return wrapper
|
|
87
86
|
|
|
@@ -90,7 +89,6 @@ def function(
|
|
|
90
89
|
|
|
91
90
|
def method(
|
|
92
91
|
endpoint: str | None = None,
|
|
93
|
-
walltime: int | None = None,
|
|
94
92
|
**user_endpoint_config: Any,
|
|
95
93
|
) -> Callable[[FunctionType], Method]:
|
|
96
94
|
"""Decorator to mark a class method for remote execution on Globus Compute.
|
|
@@ -105,9 +103,8 @@ def method(
|
|
|
105
103
|
|
|
106
104
|
Args:
|
|
107
105
|
endpoint: Globus Compute endpoint UUID
|
|
108
|
-
walltime: Maximum execution time in seconds
|
|
109
106
|
**user_endpoint_config: Options to pass through to the Executor as
|
|
110
|
-
user_endpoint_config (e.g. account, partition, etc)
|
|
107
|
+
user_endpoint_config (e.g. account, partition, walltime, etc)
|
|
111
108
|
|
|
112
109
|
Returns:
|
|
113
110
|
A decorator function that wraps the function as a Method instance
|
|
@@ -137,7 +134,7 @@ def method(
|
|
|
137
134
|
stacklevel=2,
|
|
138
135
|
)
|
|
139
136
|
|
|
140
|
-
wrapper = Method(func, endpoint,
|
|
137
|
+
wrapper = Method(func, endpoint, **user_endpoint_config)
|
|
141
138
|
functools.update_wrapper(wrapper, func)
|
|
142
139
|
return wrapper
|
|
143
140
|
|
|
@@ -51,15 +51,13 @@ class Function:
|
|
|
51
51
|
|
|
52
52
|
Attributes:
|
|
53
53
|
endpoint: Default Globus Compute endpoint UUID or None to use resolved config
|
|
54
|
-
|
|
55
|
-
default_user_endpoint_config: Default endpoint configuration (e.g., worker_init)
|
|
54
|
+
default_user_endpoint_config: Default endpoint configuration (e.g., worker_init, walltime)
|
|
56
55
|
"""
|
|
57
56
|
|
|
58
57
|
def __init__(
|
|
59
58
|
self,
|
|
60
59
|
func: FunctionType,
|
|
61
60
|
endpoint: str | None = None,
|
|
62
|
-
walltime: int | None = None,
|
|
63
61
|
**user_endpoint_config: Any,
|
|
64
62
|
) -> None:
|
|
65
63
|
"""Initialize a Function wrapper.
|
|
@@ -67,15 +65,18 @@ class Function:
|
|
|
67
65
|
Args:
|
|
68
66
|
func: The Python function to wrap
|
|
69
67
|
endpoint: Globus Compute endpoint UUID or named endpoint from `[tool.hog.<name>]` PEP 723
|
|
70
|
-
walltime: Maximum execution time in seconds (can also be set in config)
|
|
71
68
|
**user_endpoint_config: Additional endpoint configuration to pass to
|
|
72
|
-
Globus Compute Executor (e.g., worker_init commands)
|
|
69
|
+
Globus Compute Executor (e.g., worker_init commands, walltime)
|
|
73
70
|
"""
|
|
74
71
|
self._script_path: str | None = None
|
|
75
72
|
self.endpoint: str | None = endpoint
|
|
76
|
-
self.walltime: int | None = walltime
|
|
77
73
|
self.default_user_endpoint_config: dict[str, Any] = user_endpoint_config
|
|
78
74
|
|
|
75
|
+
# ShellFunction walltime - always None here to prevent conflicts with a
|
|
76
|
+
# 'walltime' endpoint config, but the attribute exists as an escape
|
|
77
|
+
# hatch if users need to set it after the function's been created
|
|
78
|
+
self.walltime: int | float | None = None
|
|
79
|
+
|
|
79
80
|
self._local_function: FunctionType = func
|
|
80
81
|
self._config_resolver: ConfigResolver | None = None
|
|
81
82
|
|
|
@@ -103,7 +104,6 @@ class Function:
|
|
|
103
104
|
self,
|
|
104
105
|
*args: Any,
|
|
105
106
|
endpoint: str | None = None,
|
|
106
|
-
walltime: int | None = None,
|
|
107
107
|
user_endpoint_config: dict[str, Any] | None = None,
|
|
108
108
|
**kwargs: Any,
|
|
109
109
|
) -> GroundhogFuture:
|
|
@@ -112,7 +112,6 @@ class Function:
|
|
|
112
112
|
Args:
|
|
113
113
|
*args: Positional arguments to pass to the function
|
|
114
114
|
endpoint: Globus Compute endpoint UUID (overrides decorator default)
|
|
115
|
-
walltime: Maximum execution time in seconds (overrides decorator default)
|
|
116
115
|
user_endpoint_config: Endpoint configuration dict (merged with decorator default)
|
|
117
116
|
**kwargs: Keyword arguments to pass to the function
|
|
118
117
|
|
|
@@ -134,12 +133,7 @@ class Function:
|
|
|
134
133
|
endpoint = endpoint or self.endpoint
|
|
135
134
|
|
|
136
135
|
decorator_config = self.default_user_endpoint_config.copy()
|
|
137
|
-
if self.walltime is not None:
|
|
138
|
-
decorator_config["walltime"] = self.walltime
|
|
139
|
-
|
|
140
136
|
call_time_config = user_endpoint_config.copy() if user_endpoint_config else {}
|
|
141
|
-
if walltime is not None:
|
|
142
|
-
call_time_config["walltime"] = walltime
|
|
143
137
|
|
|
144
138
|
# merge all config sources
|
|
145
139
|
config = self.config_resolver.resolve(
|
|
@@ -166,7 +160,9 @@ class Function:
|
|
|
166
160
|
raise ValueError("No endpoint specified")
|
|
167
161
|
|
|
168
162
|
payload = serialize((args, kwargs), use_proxy=False, proxy_threshold_mb=None)
|
|
169
|
-
shell_function = script_to_submittable(
|
|
163
|
+
shell_function = script_to_submittable(
|
|
164
|
+
self.script_path, self.name, payload, walltime=self.walltime
|
|
165
|
+
)
|
|
170
166
|
|
|
171
167
|
future: GroundhogFuture = submit_to_executor(
|
|
172
168
|
UUID(endpoint),
|
|
@@ -182,7 +178,6 @@ class Function:
|
|
|
182
178
|
self,
|
|
183
179
|
*args: Any,
|
|
184
180
|
endpoint: str | None = None,
|
|
185
|
-
walltime: int | None = None,
|
|
186
181
|
user_endpoint_config: dict[str, Any] | None = None,
|
|
187
182
|
**kwargs: Any,
|
|
188
183
|
) -> Any:
|
|
@@ -194,7 +189,6 @@ class Function:
|
|
|
194
189
|
Args:
|
|
195
190
|
*args: Positional arguments to pass to the function
|
|
196
191
|
endpoint: Globus Compute endpoint UUID (overrides decorator default)
|
|
197
|
-
walltime: Maximum execution time in seconds (overrides decorator default)
|
|
198
192
|
user_endpoint_config: Endpoint configuration dict (merged with decorator default)
|
|
199
193
|
**kwargs: Keyword arguments to pass to the function
|
|
200
194
|
|
|
@@ -210,7 +204,6 @@ class Function:
|
|
|
210
204
|
future = self.submit(
|
|
211
205
|
*args,
|
|
212
206
|
endpoint=endpoint,
|
|
213
|
-
walltime=walltime,
|
|
214
207
|
user_endpoint_config=user_endpoint_config,
|
|
215
208
|
**kwargs,
|
|
216
209
|
)
|
{groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/templates/init_script.py.jinja
RENAMED
|
@@ -11,8 +11,7 @@
|
|
|
11
11
|
# endpoint = "TODO: Add Globus Compute endpoint UUID here"
|
|
12
12
|
# # Uncomment and configure default options for "my_endpoint" here (available options vary by endpoint):
|
|
13
13
|
# # account = "my-account"
|
|
14
|
-
# # partition = "standard"
|
|
15
|
-
# # walltime = 300 {% endif %}
|
|
14
|
+
# # partition = "standard" {% endif %}
|
|
16
15
|
# ///
|
|
17
16
|
|
|
18
17
|
import groundhog_hpc as hog
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/templates/groundhog_run.py.jinja
RENAMED
|
File without changes
|
{groundhog_hpc-0.5.5 → groundhog_hpc-0.5.6}/src/groundhog_hpc/templates/shell_command.sh.jinja
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|