Add tests and docs for '--' argument separator requirement
- Add TestArgumentSeparator class with 8 tests verifying that script arguments must come after '--' separator - Update create and edit command docstrings with examples showing correct usage of '--' separator - Update argument help text to indicate "(must come after '--')" - Add "Passing Arguments to Your Script" section to README Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
c7a0b04573
commit
c601514e3d
3 changed files with 145 additions and 6 deletions
23
README.md
23
README.md
|
|
@ -28,7 +28,7 @@ mcquack list
|
|||
# Create and load an executable as a LaunchAgent
|
||||
mcquack create /path/to/your/script
|
||||
|
||||
# Create with additional arguments for the script
|
||||
# Create with additional arguments for the script (note the -- separator)
|
||||
mcquack create /path/to/your/script -- --arg1 value1 --arg2
|
||||
|
||||
# Kickstart (immediately run) the LaunchAgent
|
||||
|
|
@ -37,7 +37,7 @@ mcquack launch /path/to/your/script
|
|||
# Show the current arguments configured in the plist
|
||||
mcquack show /path/to/your/script
|
||||
|
||||
# Edit the arguments in the plist
|
||||
# Edit the arguments in the plist (note the -- separator)
|
||||
mcquack edit /path/to/your/script -- --new-arg1 --new-arg2
|
||||
|
||||
# Unload (stop) the LaunchAgent
|
||||
|
|
@ -47,6 +47,25 @@ mcquack unload /path/to/your/script
|
|||
mcquack delete /path/to/your/script
|
||||
```
|
||||
|
||||
### Passing Arguments to Your Script
|
||||
|
||||
When passing arguments to your script with `create` or `edit`, you **must** use `--` to
|
||||
separate mcquack's options from arguments intended for your script:
|
||||
|
||||
```bash
|
||||
# Correct: passes --config and --debug to your script
|
||||
mcquack create my_script.sh -- --config /path/to/config --debug
|
||||
|
||||
# Wrong: --help is interpreted as mcquack's --help flag, shows help instead
|
||||
mcquack create my_script.sh --help
|
||||
|
||||
# Correct: passes --help as an argument to your script
|
||||
mcquack create my_script.sh -- --help
|
||||
```
|
||||
|
||||
The `--` separator ensures that flags like `--help`, `--verbose`, etc. are passed to your
|
||||
script rather than being interpreted by mcquack itself.
|
||||
|
||||
## How it works
|
||||
|
||||
mcquack creates plist files in `~/Library/LaunchAgents/` with the naming convention:
|
||||
|
|
|
|||
35
mcquack.py
35
mcquack.py
|
|
@ -74,9 +74,23 @@ def list_agents() -> None:
|
|||
@app.command()
|
||||
def create(
|
||||
script: Annotated[Path, typer.Argument(help="Path to the executable script")],
|
||||
script_args: Annotated[list[str] | None, typer.Argument(help="Arguments to pass to the script")] = None,
|
||||
script_args: Annotated[
|
||||
list[str] | None,
|
||||
typer.Argument(help="Arguments to pass to the script (must come after '--')"),
|
||||
] = None,
|
||||
) -> None:
|
||||
"""Create and load a LaunchAgent for a script."""
|
||||
"""Create and load a LaunchAgent for a script.
|
||||
|
||||
To pass arguments to your script, use '--' to separate mcquack options from
|
||||
script arguments. For example:
|
||||
|
||||
mcquack create my_script.sh -- --config /path/to/config
|
||||
|
||||
Without '--', options like --help apply to mcquack itself:
|
||||
|
||||
mcquack create my_script.sh --help # Shows this help
|
||||
mcquack create my_script.sh -- --help # Passes --help to the script
|
||||
"""
|
||||
script_path = script.resolve()
|
||||
|
||||
if not script_path.exists():
|
||||
|
|
@ -170,9 +184,22 @@ def show(
|
|||
@app.command()
|
||||
def edit(
|
||||
script: Annotated[Path, typer.Argument(help="Path to the executable script")],
|
||||
script_args: Annotated[list[str] | None, typer.Argument(help="New arguments for the script")] = None,
|
||||
script_args: Annotated[
|
||||
list[str] | None,
|
||||
typer.Argument(help="New arguments for the script (must come after '--')"),
|
||||
] = None,
|
||||
) -> None:
|
||||
"""Edit the arguments in a plist."""
|
||||
"""Edit the arguments in a plist.
|
||||
|
||||
To update script arguments, use '--' to separate mcquack options from
|
||||
script arguments. For example:
|
||||
|
||||
mcquack edit my_script.sh -- --verbose --debug
|
||||
|
||||
This replaces all existing script arguments. To clear arguments, omit them:
|
||||
|
||||
mcquack edit my_script.sh
|
||||
"""
|
||||
script_path = script.resolve()
|
||||
plist_path = get_plist_path(script_path)
|
||||
|
||||
|
|
|
|||
|
|
@ -214,6 +214,99 @@ class TestDelete:
|
|||
assert "does not exist" in result.output
|
||||
|
||||
|
||||
class TestArgumentSeparator:
|
||||
"""Tests verifying that '--' separator is required for passing arguments to scripts.
|
||||
|
||||
This ensures that:
|
||||
- 'mcquack create script.sh --help' shows help for the create command
|
||||
- 'mcquack create script.sh -- --help' creates a plist with --help as a script arg
|
||||
"""
|
||||
|
||||
def test_create_help_without_separator(self, mock_dirs, mock_script, mock_launchctl):
|
||||
"""Verify that --help without -- shows create command help, not passed to script."""
|
||||
result = runner.invoke(app, ["create", str(mock_script), "--help"])
|
||||
assert result.exit_code == 0
|
||||
# Should show help text for create command
|
||||
assert "Create and load a LaunchAgent" in result.stdout or "Usage:" in result.stdout
|
||||
# Should NOT have created a plist
|
||||
plist_path = get_plist_path(mock_dirs)
|
||||
assert not plist_path.exists()
|
||||
|
||||
def test_create_help_with_separator(self, mock_dirs, mock_script, mock_launchctl):
|
||||
"""Verify that -- --help passes --help as an argument to the script."""
|
||||
result = runner.invoke(app, ["create", str(mock_script), "--", "--help"])
|
||||
assert result.exit_code == 0
|
||||
assert "Created:" in result.stdout
|
||||
|
||||
# Verify --help is in the plist as a script argument
|
||||
plist_path = get_plist_path(mock_dirs)
|
||||
assert plist_path.exists()
|
||||
program_args = read_plist_args(plist_path)
|
||||
assert "--help" in program_args
|
||||
assert program_args[1] == "--help"
|
||||
|
||||
def test_create_verbose_without_separator(self, mock_dirs, mock_script, mock_launchctl):
|
||||
"""Verify that --verbose without -- is treated as unknown option, not script arg."""
|
||||
result = runner.invoke(app, ["create", str(mock_script), "--verbose"])
|
||||
# Typer should reject unknown options
|
||||
assert result.exit_code != 0
|
||||
assert "No such option" in result.output or "no such option" in result.output.lower()
|
||||
# Should NOT have created a plist
|
||||
plist_path = get_plist_path(mock_dirs)
|
||||
assert not plist_path.exists()
|
||||
|
||||
def test_create_verbose_with_separator(self, mock_dirs, mock_script, mock_launchctl):
|
||||
"""Verify that -- --verbose passes --verbose as an argument to the script."""
|
||||
result = runner.invoke(app, ["create", str(mock_script), "--", "--verbose"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
plist_path = get_plist_path(mock_dirs)
|
||||
program_args = read_plist_args(plist_path)
|
||||
assert "--verbose" in program_args
|
||||
|
||||
def test_edit_help_without_separator(self, mock_dirs, mock_script, mock_launchctl):
|
||||
"""Verify that edit --help shows edit command help."""
|
||||
# First create an agent
|
||||
runner.invoke(app, ["create", str(mock_script)])
|
||||
|
||||
result = runner.invoke(app, ["edit", str(mock_script), "--help"])
|
||||
assert result.exit_code == 0
|
||||
assert "Edit the arguments" in result.stdout or "Usage:" in result.stdout
|
||||
|
||||
def test_edit_help_with_separator(self, mock_dirs, mock_script, mock_launchctl):
|
||||
"""Verify that edit -- --help passes --help as a new argument."""
|
||||
# First create an agent
|
||||
runner.invoke(app, ["create", str(mock_script)])
|
||||
|
||||
result = runner.invoke(app, ["edit", str(mock_script), "--", "--help"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
plist_path = get_plist_path(mock_dirs)
|
||||
program_args = read_plist_args(plist_path)
|
||||
assert "--help" in program_args
|
||||
|
||||
def test_create_mixed_args_with_separator(self, mock_dirs, mock_script, mock_launchctl):
|
||||
"""Verify multiple dash-prefixed args after -- are all passed to script."""
|
||||
result = runner.invoke(app, ["create", str(mock_script), "--", "--config", "/path", "--debug", "-v"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
plist_path = get_plist_path(mock_dirs)
|
||||
program_args = read_plist_args(plist_path)
|
||||
# All args after -- should be in the plist
|
||||
assert program_args[1:] == ["--config", "/path", "--debug", "-v"]
|
||||
|
||||
def test_create_double_dash_as_argument(self, mock_dirs, mock_script, mock_launchctl):
|
||||
"""Verify that -- can be passed as a script argument using -- --."""
|
||||
result = runner.invoke(app, ["create", str(mock_script), "--", "--", "arg_after_double_dash"])
|
||||
assert result.exit_code == 0
|
||||
|
||||
plist_path = get_plist_path(mock_dirs)
|
||||
program_args = read_plist_args(plist_path)
|
||||
# The first -- is consumed by typer, the second becomes an argument
|
||||
assert "--" in program_args
|
||||
assert "arg_after_double_dash" in program_args
|
||||
|
||||
|
||||
class TestPlistFormat:
|
||||
"""Tests verifying plist file format independently of plistlib."""
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue