Skip to content
Merged
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
42 changes: 23 additions & 19 deletions fixit/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,25 +44,29 @@ def build_parser() -> argparse.ArgumentParser:


def main(argv=None) -> int:
args = build_parser().parse_args(argv)
if args.command == "wc":
print(f"words={wordcount.count_words(args.text)} "
f"lines={wordcount.count_lines(args.text)} "
f"chars={wordcount.count_chars(args.text)}")
elif args.command == "convert":
print(CONVERSIONS[args.kind](args.value))
elif args.command == "password":
print(password.generate(args.length, use_symbols=args.symbols))
elif args.command == "uuid":
for _ in range(args.count):
print(uuid.uuid4())
elif args.command == "json":
print(jsonfmt.format_json(args.raw))
elif args.command == "palindrome":
print(textutils.is_palindrome(args.text))
elif args.command == "reverse":
print(textutils.reverse_words(args.text))
return 0
try:
args = build_parser().parse_args(argv)
if args.command == "wc":
print(f"words={wordcount.count_words(args.text)} "
f"lines={wordcount.count_lines(args.text)} "
f"chars={wordcount.count_chars(args.text)}")
elif args.command == "convert":
print(CONVERSIONS[args.kind](args.value))
elif args.command == "password":
print(password.generate(args.length, use_symbols=args.symbols))
elif args.command == "uuid":
for _ in range(args.count):
print(uuid.uuid4())
elif args.command == "json":
print(jsonfmt.format_json(args.raw))
elif args.command == "palindrome":
print(textutils.is_palindrome(args.text))
elif args.command == "reverse":
print(textutils.reverse_words(args.text))
return 0
except ValueError as e:
print(str(e), file=sys.stderr)
return 1


if __name__ == "__main__":
Expand Down
9 changes: 6 additions & 3 deletions fixit/jsonfmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@


def format_json(raw: str, indent: int = 2) -> str:
"""Return pretty-printed JSON."""
data = json.loads(raw)
return json.dumps(data, indent=indent)
try:
"""Return pretty-printed JSON."""
data = json.loads(raw)
return json.dumps(data, indent=indent)
except json.JSONDecodeError:
raise ValueError("Invalid JSON")
2 changes: 2 additions & 0 deletions fixit/password.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

def generate(length: int = 12, use_digits: bool = True, use_symbols: bool = False) -> str:
"""Return a random password of the given length."""
if length <= 0:
raise ValueError("Password length must be greater then 0!")
chars = string.ascii_letters
if use_digits:
chars += string.digits
Expand Down
7 changes: 7 additions & 0 deletions tests/test_errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from fixit import cli

def test_invalid_json_returns_1():
assert cli.main(["json", "{bad"]) == 1

def test_invalid_password_returns_1():
assert cli.main(["password", "--length", "0"]) == 1
1 change: 0 additions & 1 deletion tests/test_jsonfmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ def test_format_json():
assert format_json('{"a":1}') == '{\n "a": 1\n}'


@pytest.mark.xfail(reason="Known bug: invalid JSON raises a raw traceback instead of a friendly error")
def test_invalid_json_friendly_error():
with pytest.raises(ValueError, match="Invalid JSON"):
format_json("{not json")
1 change: 0 additions & 1 deletion tests/test_password.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ def test_no_digits():
assert not any(c.isdigit() for c in generate(50, use_digits=False))


@pytest.mark.xfail(reason="Known bug: length < 1 is not validated")
def test_invalid_length():
with pytest.raises(ValueError):
generate(0)
Loading