Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/clipstick/_clipstick.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
DUMMY_ENTRY_POINT: Final[str] = "my-cli-app"


def parse(model: type[TPydanticModel], args: list[str] | None = None) -> TPydanticModel:
def parse(
model: type[TPydanticModel],
args: list[str] | None = None,
entry_point: str | None = None,

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @playpauseandstop thanks for the pr! Much appreciated!
My use of the DUMMY_ENTRYPOINT has always bugged me a bit.
Your pr makes me think about this a bit more.

Would it be an alternative that the args: list[str] should always have the entrypoint as a first item, just like sys.argv?
This removes the entry_point parameter, the DUMMY_ENTRY_POINT and is consistent with sys.argv.

I am not sure I completely understand your usecase as you describe below. But I guess you can then use the above solution too ?

def main(*argv: str) -> int:
    args = clipstick.parse(CliArgs, argv or sys.argv[1:])
...

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forget about my above comment. I have been reading up on this on how other libs do this. for example:

https://docs.python.org/3/library/argparse.html#prog

I guess your suggestions is the proper approach.

) -> TPydanticModel:
"""Create an instance of the provided model.

Leave `args` to None in production. Only use it for testing.
Expand All @@ -19,6 +23,9 @@ def parse(model: type[TPydanticModel], args: list[str] | None = None) -> TPydant
args: The list of arguments. This is useful for testing.
Provide a list and check if your model is parsed correctly.
If not provided clipstick will evaluate the arguments from `sys.argv`.
entry_point: Entry point name. This is useful for testing.
Provide an entry point name and check for value in help output.
If not provided clipstick will evaluate an entry point from `sys.argv`.

Returns:
An instance of the pydantic class we provided as argument populated with the provided args.
Expand All @@ -30,7 +37,7 @@ def parse(model: type[TPydanticModel], args: list[str] | None = None) -> TPydant
sys.exit(1)
if args is None:
entry_point, args = sys.argv[0], sys.argv[1:]
else:
elif entry_point is None:
# Normally the first item in your sys.argv is the command/entrypoint you've entered.
# During testing you don't provide that (only the actual arguments you enter after that).
entry_point = DUMMY_ENTRY_POINT
Expand Down
6 changes: 4 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ def __init__(self, fixture_request) -> None:
self.captured_output: str | None = None
self._fixture_request = fixture_request

def __call__(self, model: type[BaseModel], args: list[str]) -> None:
def __call__(
self, model: type[BaseModel], args: list[str], entry_point: str | None = None
) -> None:
try:
console.width = 1000
console.record = True
parse(model, args)
parse(model, args, entry_point)

finally:
self.captured_output = console.export_text(clear=False)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

Usage: my-app [Arguments]

A simple model. Main description.

Arguments:
my-name A snake cased argument. [str]
8 changes: 8 additions & 0 deletions tests/test_help_command_name.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,11 @@ def test_command_name(entrypoint, monkeypatch, capture_output):
capture_output(SimpleModel, ["-h"])

assert "Usage: my-app [Arguments]" in capture_output.captured_output


@pytest.mark.parametrize("entrypoint", ["/test/my-app", "\\test\\my-app", "my-app"])
def test_command_name_from_args(entrypoint, monkeypatch, capture_output):
with pytest.raises(SystemExit):
capture_output(SimpleModel, ["-h"], entrypoint)

assert "Usage: my-app [Arguments]" in capture_output.captured_output