Skip to content

Commit

Permalink
Merge pull request #33 from glotzerlab/limit-show-output
Browse files Browse the repository at this point in the history
Limit output of `show status`
  • Loading branch information
joaander authored Aug 15, 2024
2 parents 1a287fb + b862fb9 commit dbf8d51
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 7 deletions.
4 changes: 4 additions & 0 deletions doc/src/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
*Added:*

* Edit links to documentation pages.
* New arguments to `show status` display actions that are in the requested states:
`--completed`, `--eligible`, `--submitted`, and `--waiting`.

*Changed:*

* Show `import` lines in Python examples.
* Improve the verbose output from `submit`.
* `show status` hides actions with 0 directories by default. Pass `--all` to show all
actions.

*Fixed:*

Expand Down
26 changes: 25 additions & 1 deletion doc/src/row/show/status.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Usage:
row show status [OPTIONS] [DIRECTORIES]
```

`row show status` prints a summary of all directories in the workspace.
`row show status` summarizes actions in the workflow.
The summary includes the number of directories in each
[status](../../guide/concepts/status.md) and an estimate of the remaining cost in either
CPU-hours or GPU-hours based on the number of submitted, eligible, and waiting jobs and
Expand All @@ -30,16 +30,40 @@ echo "dir1" | row show status -
Set `--action <pattern>` to choose which actions to display by name. By default, **row**
shows the status of all actions. `<pattern>` is a wildcard pattern.

### `-all`

Show all actions. By default, `show status` hides actions with 0 matching directories.

### `--completed`

Show actions with *completed* directories.

### `--eligible`

Show actions with *eligible* directories.

### `--no-header`

Hide the header in the output.

### `--submitted`

Show actions with *submitted* directories.

### `--waiting`

Show actions with *waiting* directories.

## Examples

* Show the status of the entire workspace:
```bash
row show status
```
* Show the status of all actions with eligible directories:
```bash
row show status --eligible
```
* Show the status of a specific action:
```bash
row show status --action=action
Expand Down
6 changes: 5 additions & 1 deletion src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub enum ColorMode {
pub enum ShowCommands {
/// Show the current state of the workflow.
///
/// `row show status` prints a summary of all directories in the workspace.
/// `row show status` prints a summary of all actions in the workflow.
/// The summary includes the number of directories in each status and an
/// estimate of the remaining cost in either CPU-hours or GPU-hours based
/// on the number of submitted, eligible, and waiting jobs and the
Expand All @@ -82,6 +82,10 @@ pub enum ShowCommands {
///
/// row show status
///
/// * Show the status of all actions with eligible directories
///
/// row show status --eligible
///
/// * Show the status of a specific action:
///
/// row show status --action=action
Expand Down
2 changes: 1 addition & 1 deletion src/cli/directories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub struct Arguments {
#[arg(long, display_order = 0)]
completed: bool,

/// Show submitted
/// Show submitted directories.
#[arg(long, display_order = 0)]
submitted: bool,

Expand Down
47 changes: 44 additions & 3 deletions src/cli/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use row::project::{Project, Status};
use row::workflow::ResourceCost;
use row::MultiProgressContainer;

#[allow(clippy::struct_excessive_bools)]
#[derive(Args, Debug)]
pub struct Arguments {
/// Select the actions to summarize with a wildcard pattern.
Expand All @@ -28,6 +29,26 @@ pub struct Arguments {

/// Select directories to summarize (defaults to all). Use 'status -' to read from stdin.
directories: Vec<PathBuf>,

/// Show actions with completed directories.
#[arg(long, display_order = 0, conflicts_with = "all")]
completed: bool,

/// Show actions with submitted directories.
#[arg(long, display_order = 0, conflicts_with = "all")]
submitted: bool,

/// Show actions with eligible directories.
#[arg(long, display_order = 0, conflicts_with = "all")]
eligible: bool,

/// Show actions with waiting directories.
#[arg(long, display_order = 0, conflicts_with = "all")]
waiting: bool,

/// Show all actions.
#[arg(long, display_order = 0)]
all: bool,
}

/// Format a status string for non-terminal outputs.
Expand Down Expand Up @@ -84,6 +105,19 @@ pub fn status<W: Write>(
output: &mut W,
) -> Result<(), Box<dyn Error>> {
debug!("Showing the workflow's status.");

// Show directories with selected statuses.
let mut show_completed = args.completed;
let mut show_submitted = args.submitted;
let mut show_eligible = args.eligible;
let mut show_waiting = args.waiting;
if !show_completed && !show_submitted && !show_eligible && !show_waiting {
show_completed = true;
show_submitted = true;
show_eligible = true;
show_waiting = true;
}

let action_matcher = WildMatch::new(&args.action);

let mut project = Project::open(options.io_threads, &options.cluster, multi_progress)?;
Expand Down Expand Up @@ -134,9 +168,16 @@ pub fn status<W: Write>(
cost = cost + action.resources.cost(group.len());
}

table
.rows
.push(Row::Items(make_row(action.name(), &status, &cost)));
if args.all
|| (!status.completed.is_empty() && show_completed)
|| (!status.submitted.is_empty() && show_submitted)
|| (!status.eligible.is_empty() && show_eligible)
|| (!status.waiting.is_empty() && show_waiting)
{
table
.rows
.push(Row::Items(make_row(action.name(), &status, &cost)));
}
}

if matching_action_count == 0 {
Expand Down
134 changes: 133 additions & 1 deletion tests/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ name = "two"
command = "touch workspace/{directory}/two"
products = ["two"]
previous_actions = ["one"]
[[action]]
name = "three"
command = "touch workspace/{directory}/three"
products = ["three"]
[[action.group.include]]
condition = ["/v", "<", 0]
"#,
)?;

Expand Down Expand Up @@ -141,7 +148,132 @@ fn status() -> Result<(), Box<dyn std::error::Error>> {
.assert()
.success()
.stdout(predicate::str::is_match("(?m)^one +0 +0 +10 +0")?)
.stdout(predicate::str::is_match("(?m)^two +0 +0 +0 +10")?);
.stdout(predicate::str::is_match("(?m)^two +0 +0 +0 +10")?)
.stdout(predicate::str::is_match("(?m)^three +0 +0 +0 +0")?.not());

Ok(())
}

#[test]
#[parallel]
fn status_waiting() -> Result<(), Box<dyn std::error::Error>> {
let temp = TempDir::new()?;
let _ = setup_sample_workflow(&temp, 10);

Command::cargo_bin("row")?
.args(["show", "status"])
.args(["--cluster", "none"])
.args(["--waiting"])
.current_dir(temp.path())
.env_remove("ROW_COLOR")
.env_remove("CLICOLOR")
.env("ROW_HOME", "/not/a/path")
.assert()
.success()
.stdout(predicate::str::is_match("(?m)^one +0 +0 +10 +0")?.not())
.stdout(predicate::str::is_match("(?m)^two +0 +0 +0 +10")?)
.stdout(predicate::str::is_match("(?m)^three +0 +0 +0 +0")?.not());

Ok(())
}

#[test]
#[parallel]
fn status_eligible() -> Result<(), Box<dyn std::error::Error>> {
let temp = TempDir::new()?;
let _ = setup_sample_workflow(&temp, 10);

Command::cargo_bin("row")?
.args(["show", "status"])
.args(["--cluster", "none"])
.args(["--eligible"])
.current_dir(temp.path())
.env_remove("ROW_COLOR")
.env_remove("CLICOLOR")
.env("ROW_HOME", "/not/a/path")
.assert()
.success()
.stdout(predicate::str::is_match("(?m)^one +0 +0 +10 +0")?)
.stdout(predicate::str::is_match("(?m)^two +0 +0 +0 +10")?.not())
.stdout(predicate::str::is_match("(?m)^three +0 +0 +0 +0")?.not());

Ok(())
}

#[test]
#[parallel]
fn status_submitted() -> Result<(), Box<dyn std::error::Error>> {
let temp = TempDir::new()?;
let _ = setup_sample_workflow(&temp, 10);

Command::cargo_bin("row")?
.args(["show", "status"])
.args(["--cluster", "none"])
.args(["--submitted"])
.current_dir(temp.path())
.env_remove("ROW_COLOR")
.env_remove("CLICOLOR")
.env("ROW_HOME", "/not/a/path")
.assert()
.success()
.stdout(predicate::str::is_match("(?m)^one +0 +0 +10 +0")?.not())
.stdout(predicate::str::is_match("(?m)^two +0 +0 +0 +10")?.not())
.stdout(predicate::str::is_match("(?m)^three +0 +0 +0 +0")?.not());

Ok(())
}

#[test]
#[parallel]
fn status_all() -> Result<(), Box<dyn std::error::Error>> {
let temp = TempDir::new()?;
let _ = setup_sample_workflow(&temp, 10);

Command::cargo_bin("row")?
.args(["show", "status"])
.args(["--cluster", "none"])
.args(["--all"])
.current_dir(temp.path())
.env_remove("ROW_COLOR")
.env_remove("CLICOLOR")
.env("ROW_HOME", "/not/a/path")
.assert()
.success()
.stdout(predicate::str::is_match("(?m)^one +0 +0 +10 +0")?)
.stdout(predicate::str::is_match("(?m)^two +0 +0 +0 +10")?)
.stdout(predicate::str::is_match("(?m)^three +0 +0 +0 +0")?);

Ok(())
}

#[test]
#[parallel]
fn status_completed() -> Result<(), Box<dyn std::error::Error>> {
let temp = TempDir::new()?;
let _ = setup_sample_workflow(&temp, 10);

Command::cargo_bin("row")?
.arg("submit")
.args(["--cluster", "none"])
.current_dir(temp.path())
.env_remove("ROW_COLOR")
.env_remove("CLICOLOR")
.env("ROW_HOME", "/not/a/path")
.assert()
.success();

Command::cargo_bin("row")?
.args(["show", "status"])
.args(["--cluster", "none"])
.args(["--completed"])
.current_dir(temp.path())
.env_remove("ROW_COLOR")
.env_remove("CLICOLOR")
.env("ROW_HOME", "/not/a/path")
.assert()
.success()
.stdout(predicate::str::is_match("(?m)^one +10 +0 +0 +0")?)
.stdout(predicate::str::is_match("(?m)^two +0 +0 +10 +0")?.not());

Ok(())
}
Expand Down

0 comments on commit dbf8d51

Please sign in to comment.