From d5050a706d90a86fa191e5e48084bf349b829930 Mon Sep 17 00:00:00 2001 From: Amir Mohammadi <5738695+183amir@users.noreply.github.com> Date: Wed, 23 Oct 2024 10:59:48 +0200 Subject: [PATCH 1/7] Adjust gridtk list output to fit terminal width Fixes #13 Adjust the `gridtk list` output to fit terminal width and add a `--full-output` option. * **src/gridtk/cli.py** - Update the `list_jobs` function to adjust column widths based on terminal size. - Add logic to truncate long content with ellipses in the `list_jobs` function. - Add a new option `--full-output` to the `list_jobs` command to view the full output without truncation. * **tests/test_gridtk.py** - Add unit tests to verify the new behavior of the `gridtk list` command. - Add unit tests to verify the `--full-output` option for the `gridtk list` command. * **README.md** - Update the documentation to reflect the new behavior of the `gridtk list` command. - Add information about the `--full-output` option for the `gridtk list` command. * **.devcontainer.json** - Add a devcontainer configuration file with tasks for testing, building, and launching the project. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/idiap/gridtk/issues/13?shareId=XXXX-XXXX-XXXX-XXXX). --- .devcontainer.json | 7 +++++++ README.md | 13 +++++++++++++ src/gridtk/cli.py | 27 +++++++++++++++++++++++++++ tests/test_gridtk.py | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 .devcontainer.json diff --git a/.devcontainer.json b/.devcontainer.json new file mode 100644 index 0000000..f79e7a0 --- /dev/null +++ b/.devcontainer.json @@ -0,0 +1,7 @@ +{ + "tasks": { + "test": "pixi run test", + "build": "pixi install", + "launch": "pixi run gridtk" + } +} \ No newline at end of file diff --git a/README.md b/README.md index 23bed7f..5e11324 100644 --- a/README.md +++ b/README.md @@ -251,3 +251,16 @@ or for `zsh` add the following line to your `~/.zshrc` file: ```bash eval "$(_GRIDTK_COMPLETE=zsh_source gridtk)" ``` + +### Adjusting `gridtk list` Output to Fit Terminal Width + +By default, the `gridtk list` output now adjusts to fit the terminal width, with truncation or ellipses for long content. This ensures that the output remains readable and does not span multiple lines. If you wish to view the full output without truncation, you can use the `--full-output` option: + +```bash +$ gridtk list --full-output + job-id grid-id nodes state job-name output dependencies command +-------- --------- ------- ----------- ---------- ---------------------- -------------- -------------------- + 1 136132 None PENDING (0) gridtk logs/gridtk.136132.out gridtk submit job.sh +``` + +This enhancement improves readability and allows you to quickly parse job-related information without resizing your terminal or handling multiline outputs for each job. diff --git a/src/gridtk/cli.py b/src/gridtk/cli.py index 9095521..819bd36 100644 --- a/src/gridtk/cli.py +++ b/src/gridtk/cli.py @@ -5,6 +5,7 @@ import pydoc import tempfile +import shutil from collections import defaultdict from pathlib import Path @@ -392,6 +393,12 @@ def resubmit( @cli.command(name="list") @job_filters +@click.option( + "--full-output", + is_flag=True, + default=False, + help="Show the full output without truncation.", +) @click.pass_context def list_jobs( ctx: click.Context, @@ -399,12 +406,21 @@ def list_jobs( states: list[str], names: list[str], dependents: bool, + full_output: bool, ): """List jobs in the queue, similar to sacct and squeue.""" from tabulate import tabulate from .manager import JobManager + def truncate(content, max_width): + if len(content) > max_width: + return content[: max_width - 3] + "..." + return content + + def get_terminal_width(): + return shutil.get_terminal_size((80, 20)).columns + job_manager: JobManager = ctx.meta["job_manager"] with job_manager as session: jobs = job_manager.list_jobs( @@ -428,6 +444,17 @@ def list_jobs( ",".join([str(dep_job) for dep_job in job.dependencies_ids]) ) table["command"].append("gridtk submit " + " ".join(job.command)) + + if not full_output: + terminal_width = get_terminal_width() + max_widths = { + "job-name": 20, + "output": 30, + "command": terminal_width - 100, + } + for key, max_width in max_widths.items(): + table[key] = [truncate(content, max_width) for content in table[key]] + click.echo(tabulate(table, headers="keys")) session.commit() diff --git a/tests/test_gridtk.py b/tests/test_gridtk.py index 4ebb39a..2c1550c 100644 --- a/tests/test_gridtk.py +++ b/tests/test_gridtk.py @@ -520,6 +520,44 @@ def test_submit_with_dependencies(mock_check_output, runner): ) +@patch("subprocess.check_output") +def test_list_jobs_with_truncation(mock_check_output, runner): + with runner.isolated_filesystem(): + submit_job_id = 9876543 + _submit_job( + runner=runner, mock_check_output=mock_check_output, job_id=submit_job_id + ) + + mock_check_output.return_value = _pending_job_sacct_json(submit_job_id) + result = runner.invoke(cli, ["list"]) + assert_click_runner_result(result) + assert str(submit_job_id) in result.output + assert "gridtk submit --- sleep" in result.output + assert "logs/gridtk.9876543.out" in result.output + mock_check_output.assert_called_with( + ["sacct", "-j", str(submit_job_id), "--json"], text=True + ) + + +@patch("subprocess.check_output") +def test_list_jobs_with_full_output(mock_check_output, runner): + with runner.isolated_filesystem(): + submit_job_id = 9876543 + _submit_job( + runner=runner, mock_check_output=mock_check_output, job_id=submit_job_id + ) + + mock_check_output.return_value = _pending_job_sacct_json(submit_job_id) + result = runner.invoke(cli, ["list", "--full-output"]) + assert_click_runner_result(result) + assert str(submit_job_id) in result.output + assert "gridtk submit --- sleep" in result.output + assert "logs/gridtk.9876543.out" in result.output + mock_check_output.assert_called_with( + ["sacct", "-j", str(submit_job_id), "--json"], text=True + ) + + if __name__ == "__main__": import sys From ea33b38a271089640e5cf4fa7641292478e2289e Mon Sep 17 00:00:00 2001 From: Amir Mohammadi <5738695+183amir@users.noreply.github.com> Date: Wed, 23 Oct 2024 11:00:47 +0200 Subject: [PATCH 2/7] Delete .devcontainer.json --- .devcontainer.json | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 .devcontainer.json diff --git a/.devcontainer.json b/.devcontainer.json deleted file mode 100644 index f79e7a0..0000000 --- a/.devcontainer.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "tasks": { - "test": "pixi run test", - "build": "pixi install", - "launch": "pixi run gridtk" - } -} \ No newline at end of file From 62022ed53db6ea9ef6fbd5b971908c3798635553 Mon Sep 17 00:00:00 2001 From: Amir Mohammadi Date: Tue, 29 Oct 2024 21:20:07 +0100 Subject: [PATCH 3/7] feat: add option to truncate output to terminal width in list jobs command for improved readability Also, adjust max column widths for output formatting to accommodate new options --- src/gridtk/cli.py | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/gridtk/cli.py b/src/gridtk/cli.py index 819bd36..966061a 100644 --- a/src/gridtk/cli.py +++ b/src/gridtk/cli.py @@ -4,8 +4,8 @@ # SPDX-License-Identifier: GPL-3.0-or-later import pydoc -import tempfile import shutil +import tempfile from collections import defaultdict from pathlib import Path @@ -394,11 +394,19 @@ def resubmit( @cli.command(name="list") @job_filters @click.option( + "-l", "--full-output", is_flag=True, default=False, help="Show the full output without truncation.", ) +@click.option( + "-t", + "--truncate", + is_flag=True, + default=False, + help="Truncate the output to the terminal width", +) @click.pass_context def list_jobs( ctx: click.Context, @@ -407,20 +415,18 @@ def list_jobs( names: list[str], dependents: bool, full_output: bool, + truncate: bool, ): """List jobs in the queue, similar to sacct and squeue.""" from tabulate import tabulate from .manager import JobManager - def truncate(content, max_width): + def truncate_str(content: str, max_width: int) -> str: if len(content) > max_width: return content[: max_width - 3] + "..." return content - def get_terminal_width(): - return shutil.get_terminal_size((80, 20)).columns - job_manager: JobManager = ctx.meta["job_manager"] with job_manager as session: jobs = job_manager.list_jobs( @@ -440,22 +446,36 @@ def get_terminal_width(): pass table["output"].append(output) - table["dependencies"].append( + dependencies_key = "dependencies" # if full_output else "deps" + table[dependencies_key].append( ",".join([str(dep_job) for dep_job in job.dependencies_ids]) ) table["command"].append("gridtk submit " + " ".join(job.command)) + maxcolwidths = None if not full_output: - terminal_width = get_terminal_width() + terminal_width = shutil.get_terminal_size().columns max_widths = { "job-name": 20, - "output": 30, - "command": terminal_width - 100, + "output": 15, + "command": terminal_width - 110, } - for key, max_width in max_widths.items(): - table[key] = [truncate(content, max_width) for content in table[key]] - - click.echo(tabulate(table, headers="keys")) + if truncate: + for key, max_width in max_widths.items(): + table[key] = [ + truncate_str(str(content), max_width) for content in table[key] + ] + else: + maxcolwidths = [max_widths.get(key, 15) for key in table] + + click.echo( + tabulate( + table, + headers="keys", + maxcolwidths=maxcolwidths, + maxheadercolwidths=None if full_output else 7, + ) + ) session.commit() From 861304b96e98872cc3c2e6133f410e985e0db87d Mon Sep 17 00:00:00 2001 From: Amir Mohammadi Date: Tue, 29 Oct 2024 21:52:44 +0100 Subject: [PATCH 4/7] fix: fix the tests and docs for the new gridtk list options --- README.md | 26 +++++++++++++++++++------- src/gridtk/cli.py | 17 +++++++++-------- tests/test_gridtk.py | 12 +++++++++--- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 5e11324..fe0b039 100644 --- a/README.md +++ b/README.md @@ -252,15 +252,27 @@ or for `zsh` add the following line to your `~/.zshrc` file: eval "$(_GRIDTK_COMPLETE=zsh_source gridtk)" ``` -### Adjusting `gridtk list` Output to Fit Terminal Width +### Adjusting `gridtk list` Output -By default, the `gridtk list` output now adjusts to fit the terminal width, with truncation or ellipses for long content. This ensures that the output remains readable and does not span multiple lines. If you wish to view the full output without truncation, you can use the `--full-output` option: +By default, the `gridtk list` output adjusts to fit the terminal width, with wraping. There are two options: `--truncate` and `--full-output`. +The `--truncate` option truncates the output to fit the terminal width, while the `--full-output` option displays the full output without wrapping. ```bash +$ gridtk list + job-id slurm- nodes state job- output depende command + id name ncies +-------- -------- ------- -------------- ------ --------------- --------- -------------------- + 1 506976 None UNKNOWN (None) gridtk logs/gridtk.506 gridtk submit job.sh + 976.out + $ gridtk list --full-output - job-id grid-id nodes state job-name output dependencies command --------- --------- ------- ----------- ---------- ---------------------- -------------- -------------------- - 1 136132 None PENDING (0) gridtk logs/gridtk.136132.out gridtk submit job.sh -``` + job-id slurm-id nodes state job-name output dependencies command +-------- ---------- ------- ------------- ---------- ---------------------- -------------- -------------------- + 1 506976 hcne01 COMPLETED (0) gridtk logs/gridtk.506976.out gridtk submit job.sh -This enhancement improves readability and allows you to quickly parse job-related information without resizing your terminal or handling multiline outputs for each job. +$ gridtk list --truncate + job-id slurm- nodes state job- output depende command + id name ncies +-------- -------- ------- ------------- ------ --------------- --------- -------------------- + 1 506976 hcne01 COMPLETED (0) gridtk logs/gridtk.... gridtk submit job.sh +``` diff --git a/src/gridtk/cli.py b/src/gridtk/cli.py index 966061a..5ad3088 100644 --- a/src/gridtk/cli.py +++ b/src/gridtk/cli.py @@ -436,7 +436,7 @@ def truncate_str(content: str, max_width: int) -> str: for job in jobs: table["job-id"].append(job.id) table["slurm-id"].append(job.grid_id) - table["nodes"].append(job.nodes) + table["nodes"].append(str(job.nodes)) table["state"].append(f"{job.state} ({job.exit_code})") table["job-name"].append(job.name) output = job.output_files[0].resolve() @@ -468,14 +468,15 @@ def truncate_str(content: str, max_width: int) -> str: else: maxcolwidths = [max_widths.get(key, 15) for key in table] - click.echo( - tabulate( - table, - headers="keys", - maxcolwidths=maxcolwidths, - maxheadercolwidths=None if full_output else 7, + if table: + click.echo( + tabulate( + table, + headers="keys", + maxcolwidths=maxcolwidths, + maxheadercolwidths=None if full_output else 7, + ) ) - ) session.commit() diff --git a/tests/test_gridtk.py b/tests/test_gridtk.py index 2c1550c..747ac41 100644 --- a/tests/test_gridtk.py +++ b/tests/test_gridtk.py @@ -228,6 +228,11 @@ def test_submit_triple_dash(mock_check_output: Mock, runner): @patch("subprocess.check_output") def test_list_jobs(mock_check_output, runner): with runner.isolated_filesystem(): + # test when there are no jobs + result = runner.invoke(cli, ["list"]) + assert_click_runner_result(result) + assert result.output == "" + # test when there are jobs submit_job_id = 9876543 _submit_job( runner=runner, mock_check_output=mock_check_output, job_id=submit_job_id @@ -532,8 +537,9 @@ def test_list_jobs_with_truncation(mock_check_output, runner): result = runner.invoke(cli, ["list"]) assert_click_runner_result(result) assert str(submit_job_id) in result.output - assert "gridtk submit --- sleep" in result.output - assert "logs/gridtk.9876543.out" in result.output + assert "gridtk submit --wrap sleep" in result.output + # truncated log file name + assert "logs/gridtk.987 " in result.output mock_check_output.assert_called_with( ["sacct", "-j", str(submit_job_id), "--json"], text=True ) @@ -551,7 +557,7 @@ def test_list_jobs_with_full_output(mock_check_output, runner): result = runner.invoke(cli, ["list", "--full-output"]) assert_click_runner_result(result) assert str(submit_job_id) in result.output - assert "gridtk submit --- sleep" in result.output + assert "gridtk submit --wrap sleep" in result.output assert "logs/gridtk.9876543.out" in result.output mock_check_output.assert_called_with( ["sacct", "-j", str(submit_job_id), "--json"], text=True From 241060f80de279a17a318b6a993d70e64b1eae5b Mon Sep 17 00:00:00 2001 From: Amir Mohammadi Date: Wed, 30 Oct 2024 00:11:14 +0100 Subject: [PATCH 5/7] fix: revert to full output in gridtk list by default * truncates with only 2 dots * dynamically adjusts the command column to use all the width of the terminal --- README.md | 33 ++++++------- src/gridtk/cli.py | 65 ++++++++++++++++++------- tests/test_gridtk.py | 110 ++++++++++++++++++++++++++++--------------- 3 files changed, 136 insertions(+), 72 deletions(-) diff --git a/README.md b/README.md index fe0b039..1560762 100644 --- a/README.md +++ b/README.md @@ -254,25 +254,26 @@ eval "$(_GRIDTK_COMPLETE=zsh_source gridtk)" ### Adjusting `gridtk list` Output -By default, the `gridtk list` output adjusts to fit the terminal width, with wraping. There are two options: `--truncate` and `--full-output`. -The `--truncate` option truncates the output to fit the terminal width, while the `--full-output` option displays the full output without wrapping. +By default, `gridtk list` outputs a table which migh not fit the terminal width. +You can adjust the output using the `--wrap` and `--truncate` flags. The `--wrap` +flag wraps the output to fit the terminal width, while the `--truncate` flag +truncates the output to fit the terminal width. ```bash $ gridtk list - job-id slurm- nodes state job- output depende command - id name ncies --------- -------- ------- -------------- ------ --------------- --------- -------------------- - 1 506976 None UNKNOWN (None) gridtk logs/gridtk.506 gridtk submit job.sh - 976.out - -$ gridtk list --full-output job-id slurm-id nodes state job-name output dependencies command -------- ---------- ------- ------------- ---------- ---------------------- -------------- -------------------- - 1 506976 hcne01 COMPLETED (0) gridtk logs/gridtk.506976.out gridtk submit job.sh - -$ gridtk list --truncate - job-id slurm- nodes state job- output depende command - id name ncies --------- -------- ------- ------------- ------ --------------- --------- -------------------- - 1 506976 hcne01 COMPLETED (0) gridtk logs/gridtk.... gridtk submit job.sh + 1 506993 hcne01 COMPLETED (0) gridtk logs/gridtk.506993.out gridtk submit job.sh + +$ gridtk list --wrap # --wrap or -w + job-id slurm- nodes state job-name output depende command + id ncies +-------- -------- ------- --------- ---------- ------------------- --------- ------------- + 1 506993 hcne01 COMPLETED gridtk logs/gridtk.506993. gridtk submit + (0) out job.sh + +$ gridtk list --truncate # --truncate or -t + job-id slur.. nodes state job-name output depe.. command +-------- -------- ------- -------- ---------- ------------------ -------- ----------------- + 1 506993 hcne01 COMPLE.. gridtk logs/gridtk.5069.. gridtk submit j.. ``` diff --git a/src/gridtk/cli.py b/src/gridtk/cli.py index 5ad3088..a6b34b9 100644 --- a/src/gridtk/cli.py +++ b/src/gridtk/cli.py @@ -394,11 +394,11 @@ def resubmit( @cli.command(name="list") @job_filters @click.option( - "-l", - "--full-output", + "-w", + "--wrap", is_flag=True, default=False, - help="Show the full output without truncation.", + help="Wrap the output to the terminal width", ) @click.option( "-t", @@ -414,7 +414,7 @@ def list_jobs( states: list[str], names: list[str], dependents: bool, - full_output: bool, + wrap: bool, truncate: bool, ): """List jobs in the queue, similar to sacct and squeue.""" @@ -424,7 +424,7 @@ def list_jobs( def truncate_str(content: str, max_width: int) -> str: if len(content) > max_width: - return content[: max_width - 3] + "..." + return content[: max_width - 3] + ".." return content job_manager: JobManager = ctx.meta["job_manager"] @@ -432,7 +432,7 @@ def truncate_str(content: str, max_width: int) -> str: jobs = job_manager.list_jobs( job_ids=job_ids, states=states, names=names, dependents=dependents ) - table = defaultdict(list) + table: dict[str, list[str]] = defaultdict(list) for job in jobs: table["job-id"].append(job.id) table["slurm-id"].append(job.grid_id) @@ -446,27 +446,56 @@ def truncate_str(content: str, max_width: int) -> str: pass table["output"].append(output) - dependencies_key = "dependencies" # if full_output else "deps" - table[dependencies_key].append( + table["dependencies"].append( ",".join([str(dep_job) for dep_job in job.dependencies_ids]) ) table["command"].append("gridtk submit " + " ".join(job.command)) maxcolwidths = None - if not full_output: - terminal_width = shutil.get_terminal_size().columns + full_output = not wrap and not truncate + if not full_output and table: + minimum_column_width = 7 + width_of_spaces = (len(table) - 1) * 2 + terminal_width = max( + len(table) * minimum_column_width + width_of_spaces, + shutil.get_terminal_size().columns, + ) max_widths = { - "job-name": 20, - "output": 15, - "command": terminal_width - 110, + "job-id": minimum_column_width, + "slurm-id": minimum_column_width, + "nodes": 0.1, + "state": 0.15, + "job-name": 0.2, + "output": 0.3, + "dependencies": minimum_column_width, + "command": 0.25, } + left_over_width = ( + terminal_width + - width_of_spaces + - sum(v for v in max_widths.values() if isinstance(v, int)) + ) + for key, value in max_widths.items(): + if isinstance(value, float): + max_widths[key] = int(left_over_width * value) + left_over_width = ( + terminal_width + - width_of_spaces + - sum(v for v in max_widths.values() if isinstance(v, int)) + ) + # distribute the left over width to the command column + max_widths["command"] += left_over_width + maxcolwidths = [int(max_widths[key]) for key in table] if truncate: - for key, max_width in max_widths.items(): + for key, rows in table.items(): table[key] = [ - truncate_str(str(content), max_width) for content in table[key] + truncate_str(str(row), int(max_widths[key])) for row in rows ] - else: - maxcolwidths = [max_widths.get(key, 15) for key in table] + # truncate column names + table = { + truncate_str(key, int(max_widths[key])): value + for key, value in table.items() + } if table: click.echo( @@ -474,7 +503,7 @@ def truncate_str(content: str, max_width: int) -> str: table, headers="keys", maxcolwidths=maxcolwidths, - maxheadercolwidths=None if full_output else 7, + maxheadercolwidths=maxcolwidths, ) ) session.commit() diff --git a/tests/test_gridtk.py b/tests/test_gridtk.py index 747ac41..d5a066f 100644 --- a/tests/test_gridtk.py +++ b/tests/test_gridtk.py @@ -227,11 +227,13 @@ def test_submit_triple_dash(mock_check_output: Mock, runner): @patch("subprocess.check_output") def test_list_jobs(mock_check_output, runner): - with runner.isolated_filesystem(): + # override shutil.get_terminal_size to return a fixed size with COLUMNS=80 + with runner.isolated_filesystem(), runner.isolation(env={"COLUMNS": "80"}): # test when there are no jobs result = runner.invoke(cli, ["list"]) assert_click_runner_result(result) assert result.output == "" + # test when there are jobs submit_job_id = 9876543 _submit_job( @@ -245,6 +247,38 @@ def test_list_jobs(mock_check_output, runner): mock_check_output.assert_called_with( ["sacct", "-j", str(submit_job_id), "--json"], text=True ) + # full command + assert "gridtk submit --wrap sleep\n" in result.output + # full log file name + assert "logs/gridtk.9876543.out " in result.output + + # test gridtk list --truncate + result = runner.invoke(cli, ["list", "--truncate"]) + assert_click_runner_result(result) + assert str(submit_job_id) in result.output + mock_check_output.assert_called_with( + ["sacct", "-j", str(submit_job_id), "--json"], text=True + ) + # truncated command + assert "gridtk sub..\n" in result.output + # truncated log file name + assert "logs/gridt.. " in result.output + + # test gridtk list --wrap + result = runner.invoke(cli, ["list", "--wrap"]) + assert_click_runner_result(result) + assert str(submit_job_id) in result.output + mock_check_output.assert_called_with( + ["sacct", "-j", str(submit_job_id), "--json"], text=True + ) + # wraped command + assert "gridtk" in result.output + assert "submit" in result.output + assert "--wrap" in result.output + assert "sleep" in result.output + # wraped log file name + assert "logs/gridtk.9 " in result.output + assert "876543.out " in result.output @patch("subprocess.check_output") @@ -525,43 +559,43 @@ def test_submit_with_dependencies(mock_check_output, runner): ) -@patch("subprocess.check_output") -def test_list_jobs_with_truncation(mock_check_output, runner): - with runner.isolated_filesystem(): - submit_job_id = 9876543 - _submit_job( - runner=runner, mock_check_output=mock_check_output, job_id=submit_job_id - ) - - mock_check_output.return_value = _pending_job_sacct_json(submit_job_id) - result = runner.invoke(cli, ["list"]) - assert_click_runner_result(result) - assert str(submit_job_id) in result.output - assert "gridtk submit --wrap sleep" in result.output - # truncated log file name - assert "logs/gridtk.987 " in result.output - mock_check_output.assert_called_with( - ["sacct", "-j", str(submit_job_id), "--json"], text=True - ) - - -@patch("subprocess.check_output") -def test_list_jobs_with_full_output(mock_check_output, runner): - with runner.isolated_filesystem(): - submit_job_id = 9876543 - _submit_job( - runner=runner, mock_check_output=mock_check_output, job_id=submit_job_id - ) - - mock_check_output.return_value = _pending_job_sacct_json(submit_job_id) - result = runner.invoke(cli, ["list", "--full-output"]) - assert_click_runner_result(result) - assert str(submit_job_id) in result.output - assert "gridtk submit --wrap sleep" in result.output - assert "logs/gridtk.9876543.out" in result.output - mock_check_output.assert_called_with( - ["sacct", "-j", str(submit_job_id), "--json"], text=True - ) +# @patch("subprocess.check_output") +# def test_list_jobs_with_truncation(mock_check_output, runner): +# with runner.isolated_filesystem(): +# submit_job_id = 9876543 +# _submit_job( +# runner=runner, mock_check_output=mock_check_output, job_id=submit_job_id +# ) + +# mock_check_output.return_value = _pending_job_sacct_json(submit_job_id) +# result = runner.invoke(cli, ["list"]) +# assert_click_runner_result(result) +# assert str(submit_job_id) in result.output +# assert "gridtk submit --wrap sleep" in result.output +# # wraped log file name +# assert "logs/gridtk.987 " in result.output +# mock_check_output.assert_called_with( +# ["sacct", "-j", str(submit_job_id), "--json"], text=True +# ) + + +# @patch("subprocess.check_output") +# def test_list_jobs_with_full_output(mock_check_output, runner): +# with runner.isolated_filesystem(): +# submit_job_id = 9876543 +# _submit_job( +# runner=runner, mock_check_output=mock_check_output, job_id=submit_job_id +# ) + +# mock_check_output.return_value = _pending_job_sacct_json(submit_job_id) +# result = runner.invoke(cli, ["list", "--full-output"]) +# assert_click_runner_result(result) +# assert str(submit_job_id) in result.output +# assert "gridtk submit --wrap sleep" in result.output +# assert "logs/gridtk.9876543.out" in result.output +# mock_check_output.assert_called_with( +# ["sacct", "-j", str(submit_job_id), "--json"], text=True +# ) if __name__ == "__main__": From 899eed70547f1bd739a57e25935a293e3a9eb73c Mon Sep 17 00:00:00 2001 From: Amir Mohammadi Date: Wed, 30 Oct 2024 00:25:09 +0100 Subject: [PATCH 6/7] fix: do not add leftover to command width --- README.md | 18 +++++++++--------- src/gridtk/cli.py | 7 ------- tests/test_gridtk.py | 2 +- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 1560762..72c7272 100644 --- a/README.md +++ b/README.md @@ -263,17 +263,17 @@ truncates the output to fit the terminal width. $ gridtk list job-id slurm-id nodes state job-name output dependencies command -------- ---------- ------- ------------- ---------- ---------------------- -------------- -------------------- - 1 506993 hcne01 COMPLETED (0) gridtk logs/gridtk.506993.out gridtk submit job.sh + 1 506994 hcne01 COMPLETED (0) gridtk logs/gridtk.506994.out gridtk submit job.sh $ gridtk list --wrap # --wrap or -w - job-id slurm- nodes state job-name output depende command - id ncies --------- -------- ------- --------- ---------- ------------------- --------- ------------- - 1 506993 hcne01 COMPLETED gridtk logs/gridtk.506993. gridtk submit - (0) out job.sh + job-id slurm- nodes state job-name output depende command + id ncies +-------- -------- ------- -------- ---------- ----------------- --------- ------------- + 1 506994 hcne0 COMPLETE gridtk logs/gridtk.50699 gridtk submit + 1 D (0) 4.out job.sh $ gridtk list --truncate # --truncate or -t - job-id slur.. nodes state job-name output depe.. command --------- -------- ------- -------- ---------- ------------------ -------- ----------------- - 1 506993 hcne01 COMPLE.. gridtk logs/gridtk.5069.. gridtk submit j.. + job-id slur.. nodes state job-name output depe.. command +-------- -------- ------- ------- ---------- ---------------- -------- ------------- + 1 506994 hc.. COMPL.. gridtk logs/gridtk.50.. gridtk subm.. ``` diff --git a/src/gridtk/cli.py b/src/gridtk/cli.py index a6b34b9..6a4a790 100644 --- a/src/gridtk/cli.py +++ b/src/gridtk/cli.py @@ -478,13 +478,6 @@ def truncate_str(content: str, max_width: int) -> str: for key, value in max_widths.items(): if isinstance(value, float): max_widths[key] = int(left_over_width * value) - left_over_width = ( - terminal_width - - width_of_spaces - - sum(v for v in max_widths.values() if isinstance(v, int)) - ) - # distribute the left over width to the command column - max_widths["command"] += left_over_width maxcolwidths = [int(max_widths[key]) for key in table] if truncate: for key, rows in table.items(): diff --git a/tests/test_gridtk.py b/tests/test_gridtk.py index d5a066f..46c6404 100644 --- a/tests/test_gridtk.py +++ b/tests/test_gridtk.py @@ -260,7 +260,7 @@ def test_list_jobs(mock_check_output, runner): ["sacct", "-j", str(submit_job_id), "--json"], text=True ) # truncated command - assert "gridtk sub..\n" in result.output + assert "gridtk s..\n" in result.output # truncated log file name assert "logs/gridt.. " in result.output From 38ab1a2be079dedecbfdefeffa4ff7410727d73f Mon Sep 17 00:00:00 2001 From: Amir Mohammadi Date: Wed, 30 Oct 2024 00:29:38 +0100 Subject: [PATCH 7/7] chore(tests): remove commented-out test cases for list jobs functionality --- tests/test_gridtk.py | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/tests/test_gridtk.py b/tests/test_gridtk.py index 46c6404..b651dbd 100644 --- a/tests/test_gridtk.py +++ b/tests/test_gridtk.py @@ -559,45 +559,6 @@ def test_submit_with_dependencies(mock_check_output, runner): ) -# @patch("subprocess.check_output") -# def test_list_jobs_with_truncation(mock_check_output, runner): -# with runner.isolated_filesystem(): -# submit_job_id = 9876543 -# _submit_job( -# runner=runner, mock_check_output=mock_check_output, job_id=submit_job_id -# ) - -# mock_check_output.return_value = _pending_job_sacct_json(submit_job_id) -# result = runner.invoke(cli, ["list"]) -# assert_click_runner_result(result) -# assert str(submit_job_id) in result.output -# assert "gridtk submit --wrap sleep" in result.output -# # wraped log file name -# assert "logs/gridtk.987 " in result.output -# mock_check_output.assert_called_with( -# ["sacct", "-j", str(submit_job_id), "--json"], text=True -# ) - - -# @patch("subprocess.check_output") -# def test_list_jobs_with_full_output(mock_check_output, runner): -# with runner.isolated_filesystem(): -# submit_job_id = 9876543 -# _submit_job( -# runner=runner, mock_check_output=mock_check_output, job_id=submit_job_id -# ) - -# mock_check_output.return_value = _pending_job_sacct_json(submit_job_id) -# result = runner.invoke(cli, ["list", "--full-output"]) -# assert_click_runner_result(result) -# assert str(submit_job_id) in result.output -# assert "gridtk submit --wrap sleep" in result.output -# assert "logs/gridtk.9876543.out" in result.output -# mock_check_output.assert_called_with( -# ["sacct", "-j", str(submit_job_id), "--json"], text=True -# ) - - if __name__ == "__main__": import sys