Skip to content

Commit 6f43eda

Browse files
committed
fix: Fix issues pointed by the linter
1 parent 351262e commit 6f43eda

3 files changed

Lines changed: 58 additions & 24 deletions

File tree

pyproject.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,10 @@ select = [
109109
"I001", # isort
110110
"I002", # isort
111111
]
112-
ignore = ["RUF012"]
112+
ignore = [
113+
"RUF012",
114+
"PLR0915", # too many statements
115+
]
113116

114117
[tool.ruff.lint.pydocstyle]
115118
convention = "numpy"

src/makim/core.py

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ def _call_shell_app(
192192
out_stream: TextIO = sys.stdout,
193193
err_stream: TextIO = sys.stderr,
194194
exit_on_error: bool = True,
195-
) -> None:
195+
) -> bool:
196196
self._load_shell_app()
197197

198198
fd, filepath = tempfile.mkstemp(suffix=self.tmp_suffix, text=True)
@@ -224,6 +224,7 @@ def _call_shell_app(
224224
e.exit_code or 1,
225225
exit_on_error=exit_on_error,
226226
)
227+
return False
227228
except KeyboardInterrupt:
228229
os.close(fd)
229230
pid = p.pid
@@ -233,10 +234,11 @@ def _call_shell_app(
233234
MakimError.SH_KEYBOARD_INTERRUPT,
234235
)
235236
os.close(fd)
237+
return True
236238

237239
def _call_shell_remote(
238240
self, cmd: str, host_config: dict[str, Any], exit_on_error: bool = True
239-
) -> None:
241+
) -> bool:
240242
try:
241243
# Render the host configuration values
242244
env, _ = self._load_scoped_data('task')
@@ -266,25 +268,30 @@ def _call_shell_remote(
266268
MakimError.SSH_EXECUTION_ERROR,
267269
exit_on_error=exit_on_error,
268270
)
271+
return False
269272

270273
ssh.close()
274+
return True
271275
except paramiko.AuthenticationException:
272276
MakimLogs.raise_error(
273277
f'Authentication failed for host {host_config["host"]}',
274278
MakimError.SSH_AUTHENTICATION_FAILED,
275279
)
280+
return False
276281
except paramiko.SSHException as ssh_exception:
277282
MakimLogs.raise_error(
278283
f'SSH error: {ssh_exception!s}',
279284
MakimError.SSH_CONNECTION_ERROR,
280285
exit_on_error=exit_on_error,
281286
)
287+
return False
282288
except Exception as e:
283289
MakimLogs.raise_error(
284290
f'Unexpected error during remote execution: {e!s}',
285291
MakimError.SSH_EXECUTION_ERROR,
286292
exit_on_error=exit_on_error,
287293
)
294+
return False
288295

289296
def _render_host_config(
290297
self, host_config: dict[str, Any], env: dict[str, str]
@@ -914,7 +921,7 @@ def _execute_hook(
914921

915922
def _run_command(
916923
self, args: dict[str, Any], exit_on_error: bool = True
917-
) -> None:
924+
) -> bool:
918925
cmd = self.task_data.get('run', '').strip()
919926
remote_host = self.task_data.get('remote')
920927

@@ -968,7 +975,7 @@ def _run_command(
968975

969976
width, _ = get_terminal_size()
970977

971-
def process_matrix_combination(matrix_vars: dict[str, Any]) -> None:
978+
def process_matrix_combination(matrix_vars: dict[str, Any]) -> bool:
972979
# Update environment variables
973980
for k, v in env.items():
974981
os.environ[k] = v
@@ -1009,27 +1016,33 @@ def process_matrix_combination(matrix_vars: dict[str, Any]) -> None:
10091016
""",
10101017
MakimError.REMOTE_HOST_NOT_FOUND,
10111018
)
1012-
self._call_shell_remote(
1019+
return self._call_shell_remote(
10131020
current_cmd,
10141021
cast(dict[str, Any], host_config),
10151022
exit_on_error=exit_on_error,
10161023
)
10171024
else:
10181025
out_stream, err_stream = self._get_output_stream()
1019-
self._call_shell_app(
1026+
return self._call_shell_app(
10201027
current_cmd,
10211028
out_stream,
10221029
err_stream,
10231030
exit_on_error=exit_on_error,
10241031
)
1032+
return True
10251033

10261034
# Run command for each matrix combination
1035+
all_success = True
10271036
for matrix_vars in matrix_combinations or [{}]:
1028-
process_matrix_combination(matrix_vars)
1037+
if not process_matrix_combination(matrix_vars):
1038+
all_success = False
1039+
if exit_on_error:
1040+
break
10291041

10301042
# move back the environment variable to the previous values
10311043
os.environ.clear()
10321044
os.environ.update(self.env_scoped)
1045+
return all_success
10331046

10341047
def _get_output_stream(self) -> tuple[TextIO, TextIO]:
10351048
"""Set up logging streams based on task log configuration."""
@@ -1088,8 +1101,7 @@ async def _run_with_retry(self, args: dict[str, Any]) -> bool:
10881101

10891102
if not retry_config or retry_count == 1:
10901103
try:
1091-
self._run_command(args, exit_on_error=False)
1092-
return True
1104+
return self._run_command(args, exit_on_error=False)
10931105
except Exception:
10941106
return False
10951107

@@ -1099,20 +1111,23 @@ async def _run_with_retry(self, args: dict[str, Any]) -> bool:
10991111
MakimLogs.print_info(
11001112
f'[Retry] Attempt {attempt}/{retry_count}'
11011113
)
1102-
self._run_command(args, exit_on_error=False)
1103-
return True
1114+
if self._run_command(args, exit_on_error=False):
1115+
return True
11041116
except Exception:
1105-
if attempt == retry_count:
1106-
MakimLogs.print_warning(
1107-
f'[Retry] All {retry_count} retries failed.'
1108-
)
1109-
return False
1110-
attempt += 1
1117+
# Exception caught, will retry or fail based on retry_count
1118+
pass # nosec B110
1119+
1120+
if attempt == retry_count:
11111121
MakimLogs.print_warning(
1112-
f'[Retry] Attempt {attempt}/{retry_count}.'
1113-
f' Retrying in {delay} seconds...',
1122+
f'[Retry] All {retry_count} retries failed.'
11141123
)
1115-
await asyncio.sleep(delay)
1124+
return False
1125+
attempt += 1
1126+
MakimLogs.print_warning(
1127+
f'[Retry] Attempt {attempt}/{retry_count}.'
1128+
f' Retrying in {delay} seconds...',
1129+
)
1130+
await asyncio.sleep(delay)
11161131
return False
11171132

11181133
# public methods
@@ -1134,7 +1149,20 @@ def load(
11341149
self.env = self._load_dotenv(self.global_data)
11351150

11361151
def run(self, args: dict[str, Any]) -> bool:
1137-
"""Run makim task code."""
1152+
"""Run makim task code.
1153+
1154+
Returns
1155+
-------
1156+
bool
1157+
True if the task completed successfully or if ignore-errors is
1158+
enabled, False otherwise.
1159+
1160+
Note
1161+
----
1162+
API Change: This method now returns bool instead of None. This change
1163+
enables proper failure hook execution and ignore-errors functionality.
1164+
External callers should be updated to handle the boolean return value.
1165+
"""
11381166
self.args = args
11391167

11401168
# setup
@@ -1170,7 +1198,7 @@ def run(self, args: dict[str, Any]) -> bool:
11701198
if retry:
11711199
success = asyncio.run(self._run_with_retry(args))
11721200
else:
1173-
self._run_command(
1201+
success = self._run_command(
11741202
args, exit_on_error=not (failure_hook or ignore_errors)
11751203
)
11761204
except Exception:
@@ -1179,7 +1207,9 @@ def run(self, args: dict[str, Any]) -> bool:
11791207
if not success and failure_hook:
11801208
self._run_hooks(args, 'failure')
11811209

1182-
if success or ignore_errors:
1210+
# Run post-run hooks if task succeeded, or no failure hook exists, or
1211+
# ignoring errors
1212+
if success or not failure_hook or ignore_errors:
11831213
self._run_hooks(args, 'post-run')
11841214

11851215
return success or ignore_errors

tests/smoke/.makim-skip-errors.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ groups:
2727
clean-logs:
2828
help: This task removes all log files
2929
run: |
30+
mkdir -p ./tests/smoke/logs
3031
rm -f ./tests/smoke/logs/failure_hook.txt
3132
rm -f ./tests/smoke/logs/post_hook.txt
3233
rm -f ./tests/smoke/logs/pre_hook.txt

0 commit comments

Comments
 (0)