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
7 changes: 7 additions & 0 deletions httpie/cli/argtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ def __call__(self, s: str) -> KeyValueArg:
break

else:
# Check if this looks like it should be a continuation of a previous value
# (i.e., it's a string without any separator, likely due to unquoted shell args)
if all(c not in s for c in self.special_characters):
raise argparse.ArgumentTypeError(
f'{s!r} is not a valid value. Did you mean to quote it as part of a previous item? '
f'For example: field="value {s}"'
)
raise argparse.ArgumentTypeError(f'{s!r} is not a valid value')

return self.key_value_class(key=key, value=value, sep=sep, orig=s)
Expand Down
17 changes: 17 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ def test_invalid_items(self):
for item in items:
pytest.raises(argparse.ArgumentTypeError, self.key_value_arg, item)

def test_invalid_item_without_separator_provides_helpful_error(self):
"""Test that items without separators show a helpful error message."""
with pytest.raises(argparse.ArgumentTypeError) as exc_info:
self.key_value_arg('Bar')
assert 'Did you mean to quote it' in str(exc_info.value)
assert 'field="value Bar"' in str(exc_info.value)

def test_escape_separator(self):
items = RequestItems.from_args([
# headers
Expand Down Expand Up @@ -63,6 +70,16 @@ def test_backslash_before_non_special_character_does_not_escape(
actual = self.key_value_arg(string)
assert actual == expected

@pytest.mark.parametrize('item_string, expected_value', [
('field=value with spaces', 'value with spaces'),
('field_name="Foo Bar"', '"Foo Bar"'),
('data=Hello World Test', 'Hello World Test'),
])
def test_values_with_spaces_when_properly_quoted(self, item_string, expected_value):
"""Test that values with spaces work correctly when properly quoted."""
result = self.key_value_arg(item_string)
assert result.value == expected_value

def test_escape_longsep(self):
items = RequestItems.from_args([
self.key_value_arg(r'bob\:==foo'),
Expand Down
Loading