Skip to content

Commit

Permalink
Modify the cli to accept stdin for pipe command purpose
Browse files Browse the repository at this point in the history
  • Loading branch information
mangiucugna committed Feb 18, 2025
1 parent 5959681 commit 092f1e8
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 11 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
[project]
name = "json_repair"
version = "0.38.0"
version = "0.39.0"
license = {file = "LICENSE"}
authors = [
{ name="Stefano Baccianella", email="4247706+mangiucugna@users.noreply.github.com" },
Expand Down
27 changes: 20 additions & 7 deletions src/json_repair/json_repair.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ def cli(inline_args: Optional[List[str]] = None) -> int:
Args:
inline_args (Optional[List[str]]): List of command-line arguments for testing purposes. Defaults to None.
- filename (str): The JSON file to repair
- filename (str): The JSON file to repair. If omitted, the JSON is read from stdin.
- -i, --inline (bool): Replace the file inline instead of returning the output to stdout.
- -o, --output TARGET (str): If specified, the output will be written to TARGET filename instead of stdout.
- --ensure_ascii (bool): Pass ensure_ascii=True to json.dumps(). Will pass False otherwise.
Expand All @@ -174,9 +174,15 @@ def cli(inline_args: Optional[List[str]] = None) -> int:
Example:
>>> cli(['example.json', '--indent', '4'])
>>> cat json.txt | json_repair
"""
parser = argparse.ArgumentParser(description="Repair and parse JSON files.")
parser.add_argument("filename", help="The JSON file to repair")
# Make the filename argument optional; if omitted, we will read from stdin.
parser.add_argument(
"filename",
nargs="?",
help="The JSON file to repair (if omitted, reads from stdin)",
)
parser.add_argument(
"-i",
"--inline",
Expand Down Expand Up @@ -204,9 +210,12 @@ def cli(inline_args: Optional[List[str]] = None) -> int:
if inline_args is None: # pragma: no cover
args = parser.parse_args()
else:
args = parser.parse_args(
inline_args
) # This is needed so this function is testable
args = parser.parse_args(inline_args)

# Inline mode requires a filename, so error out if none was provided.
if args.inline and not args.filename: # pragma: no cover
print("Error: Inline mode requires a filename", file=sys.stderr)
sys.exit(1)

if args.inline and args.output: # pragma: no cover
print("Error: You cannot pass both --inline and --output", file=sys.stderr)
Expand All @@ -217,8 +226,12 @@ def cli(inline_args: Optional[List[str]] = None) -> int:
ensure_ascii = True

try:
result = from_file(args.filename)

# Use from_file if a filename is provided; otherwise read from stdin.
if args.filename:
result = from_file(args.filename)
else:
data = sys.stdin.read()
result = loads(data)
if args.inline or args.output:
with open(args.output or args.filename, mode="w") as fd:
json.dump(result, fd, indent=args.indent, ensure_ascii=ensure_ascii)
Expand Down
4 changes: 2 additions & 2 deletions tests/profiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"sunt",
"ipsum"
],
"friends": [
"friends": [ // comment
{
"id": 0,
"name": "Cara Shepherd"
Expand Down Expand Up @@ -107,7 +107,7 @@
{
"_id": "655b6625870da431bcf5e0c2",
"index": 2,
"guid": "b17f6e3f-c898-4334-abbf-05cf222f143b",
"guid": "b17f6e3f-c898-4334-abbf-05cf222f143b,
"isActive": false,
"balance": "$1,493.77",
"picture": "http://placehold.it/32x32",
Expand Down
13 changes: 12 additions & 1 deletion tests/test_json_repair.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import os.path
import pathlib
import tempfile
import io

def test_basic_types_valid():
assert repair_json("True", return_objects=True) == ""
Expand Down Expand Up @@ -316,4 +317,14 @@ def test_cli(capsys):
finally:
# Clean up - delete the temporary file
os.remove(temp_path)
os.remove(tempout_path)
os.remove(tempout_path)

# Prepare a JSON string that needs to be repaired.
test_input = "{key:value"
# Expected output when running cli with --indent 0.
expected_output = '{\n"key": "value"\n}\n'
# Patch sys.stdin so that cli() reads from it instead of a file.
with patch('sys.stdin', new=io.StringIO(test_input)):
cli(inline_args=['--indent', 0])
captured = capsys.readouterr()
assert captured.out == expected_output

0 comments on commit 092f1e8

Please sign in to comment.