Skip to content

Commit

Permalink
Piped args default to no-ops for run and list (#1)
Browse files Browse the repository at this point in the history
* Piped args default to no-ops for `run` and `list`

* Update PR template
  • Loading branch information
jacksmith15 authored Nov 23, 2021
1 parent e11e770 commit 51145d0
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 13 deletions.
4 changes: 2 additions & 2 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ _What has changed? This should match `CHANGELOG.md`._

## Before asking for a review

- [ ] Target branch is `master`
- [ ] [`[Unreleased]`](../blob/master/CHANGELOG.md#unreleased) section in [CHANGELOG.md](../blob/master/CHANGELOG.md) is updated.
- [ ] Target branch is `main`
- [ ] [`[Unreleased]`](../blob/main/CHANGELOG.md#unreleased) section in [CHANGELOG.md](../blob/main/CHANGELOG.md) is updated.
- [ ] I reviewed the "Files changed" tab and self-annotated anything unexpected.

## Before review (reviewer)
Expand Down
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ Types of changes are:
* **Fixed** for any bug fixes.

## [Unreleased]

### Changed
* `run` and `list` are now no-ops when input is piped to the command, and no arguments are provided. Behaviour when providing regular arguments is unchanged. This makes these commands easier to chain in scripts. E.g.
- `workspace reverse | workspace run` will not run any commands
- `workspace run` will still run a command in every project

## [0.1.0] - 2021-11-01
### Added
Expand Down
10 changes: 7 additions & 3 deletions tests/cli/commands/helpers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import pty
import shlex
import subprocess
from pathlib import Path
Expand All @@ -20,11 +21,14 @@ def format_output(stdout: str, stderr: str) -> str:
]
).strip()

if isinstance(command, str):
command = shlex.split(command)
if isinstance(command, list):
command = shlex.join(map(str, command))

# Ensure stdin looks like a tty, as this affects default argument behaviour
_, stdin = pty.openpty()

try:
result = subprocess.run(command, check=True, capture_output=True, cwd=cwd, text=True)
result = subprocess.run(command, check=True, capture_output=True, cwd=cwd, text=True, shell=True, stdin=stdin)
except subprocess.CalledProcessError as exc:
exc.text = format_output(exc.stdout, exc.stderr) # type: ignore[attr-defined]
if assert_success:
Expand Down
15 changes: 15 additions & 0 deletions tests/cli/commands/test_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,18 @@ def should_output_to_json():
"depends_on": [],
},
]

@staticmethod
def should_have_different_default_behaviour_for_pipes():
# GIVEN I have two projects
paths = {"libs/my-library", "libs/my-other-library"}
for path in paths:
run(["workspace", "new", "--type", "poetry", path])
# THEN workspace list shows all libs with no args or pipe
assert run("workspace list --output names").stdout.splitlines() == ["my-library", "my-other-library"]
# AND workspace list shows specified project when provided as arg
assert run(["workspace", "list", "--output", "names", "my-library"]).stdout.splitlines() == ["my-library"]
# AND workspace list shows specified project when provided via pipe
assert run("workspace reverse libs/my-library/foo | workspace list --output names").stdout.splitlines() == ["my-library"]
# AND workspace list shows nothing when empty input is provided via pipe
assert run("workspace reverse some/path | workspace list --output names").stdout.splitlines() == []
4 changes: 2 additions & 2 deletions tests/cli/commands/test_remove.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def should_remove_specified_project():
# WHEN I remove the project
run(["workspace", "remove", "my-library"])
# THEN the project should no longer be tracked
assert run(["workspace", "list", "--output", "names"]).text == ""
assert run(["workspace", "list", "--output", "names"]).stdout == ""
# AND the project should still exist
assert (WORKSPACE_ROOT / path).exists()

Expand All @@ -22,7 +22,7 @@ def should_delete_when_flag_is_set():
# WHEN I remove the project
run(["workspace", "remove", "my-library", "--delete"])
# THEN the project should no longer be tracked
assert run(["workspace", "list", "--output", "names"]).text == ""
assert run(["workspace", "list", "--output", "names"]).stdout == ""
# AND the project should still exist
assert not (WORKSPACE_ROOT / path).exists()

Expand Down
4 changes: 2 additions & 2 deletions workspace/cli/commands/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ def list_(specifiers: Tuple[str, ...], output: str = "default"):
"""List projects tracked in the workspace."""
workspace = Workspace.from_path()

target_set = set(workspace.projects) if click.get_text_stream("stdin").isatty() else set()
if specifiers:
target_set = resolve_specifiers(workspace, specifiers)
else:
target_set = set(workspace.projects)

if not target_set:
theme.echo("<w>No projects selected.</w>")
sys.exit(0)

for name in sorted(target_set):
Expand Down
5 changes: 2 additions & 3 deletions workspace/cli/commands/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,9 @@ def run(specifiers: Tuple[str], command: str, parallel: bool = False):
"""
workspace = Workspace.from_path()

target_set = set(workspace.projects) if click.get_text_stream("stdin").isatty() else set()
if specifiers:
target_set = resolve_specifiers(workspace, set(specifiers))
else:
target_set = set(workspace.projects)
target_set = resolve_specifiers(workspace, specifiers)

if not target_set:
theme.echo("<w>No projects selected.</w>")
Expand Down

0 comments on commit 51145d0

Please sign in to comment.