8
8
from copy import deepcopy
9
9
from functools import partial
10
10
from io import StringIO
11
+ from jmespath import compile as jp_compile
11
12
from pygments import highlight
12
13
from pygments .formatters import TerminalFormatter
13
14
from pygments .lexers import JsonLexer , YamlLexer , TOMLLexer
17
18
sys .path .insert (0 , BASE_DIR )
18
19
import jsonfmt
19
20
20
-
21
- with open (f' { BASE_DIR } /test/example.json' ) as json_fp :
21
+ JSON_FILE = f' { BASE_DIR } /test/example.json'
22
+ with open (JSON_FILE ) as json_fp :
22
23
JSON_TEXT = json_fp .read ()
23
24
24
- with open (f'{ BASE_DIR } /test/example.toml' ) as toml_fp :
25
+ TOML_FILE = f'{ BASE_DIR } /test/example.toml'
26
+ with open (TOML_FILE ) as toml_fp :
25
27
TOML_TEXT = toml_fp .read ()
26
28
27
- with open (f'{ BASE_DIR } /test/example.yaml' ) as yaml_fp :
29
+ YAML_FILE = f'{ BASE_DIR } /test/example.yaml'
30
+ with open (YAML_FILE ) as yaml_fp :
28
31
YAML_TEXT = yaml_fp .read ()
29
32
30
33
@@ -44,12 +47,21 @@ def color(text, format):
44
47
45
48
46
49
class FakeStdStream (StringIO ):
50
+
51
+ def __init__ (self , initial_value = '' , newline = '\n ' , tty = True ):
52
+ super ().__init__ (initial_value , newline )
53
+ self ._istty = tty
54
+
47
55
def isatty (self ):
48
- return True
56
+ return self . _istty
49
57
50
58
def read (self ):
51
59
self .seek (0 )
52
- return super ().read ()
60
+ content = super ().read ()
61
+
62
+ self .seek (0 )
63
+ self .truncate ()
64
+ return content
53
65
54
66
55
67
class FakeStdIn (FakeStdStream ):
@@ -84,28 +96,27 @@ def test_is_clipboard_available(self):
84
96
85
97
def test_parse_to_pyobj (self ):
86
98
# normal parameters test
87
- matched_obj = jsonfmt .parse_to_pyobj (JSON_TEXT , "actions[:].calorie" )
99
+ matched_obj = jsonfmt .parse_to_pyobj (JSON_TEXT , jp_compile ( "actions[:].calorie" ) )
88
100
self .assertEqual (matched_obj , ([294.9 , - 375 ], 'json' ))
89
- matched_obj = jsonfmt .parse_to_pyobj (TOML_TEXT , "actions[*].name" )
101
+ matched_obj = jsonfmt .parse_to_pyobj (TOML_TEXT , jp_compile ( "actions[*].name" ) )
90
102
self .assertEqual (matched_obj , (['eat' , 'sport' ], 'toml' ))
91
- matched_obj = jsonfmt .parse_to_pyobj (YAML_TEXT , "actions[*].date" )
103
+ matched_obj = jsonfmt .parse_to_pyobj (YAML_TEXT , jp_compile ( "actions[*].date" ) )
92
104
self .assertEqual (matched_obj , (['2021-03-02' , '2023-04-27' ], 'yaml' ))
93
105
# test not exists key
94
- matched_obj = jsonfmt .parse_to_pyobj (TOML_TEXT , "not_exist_key" )
106
+ matched_obj = jsonfmt .parse_to_pyobj (TOML_TEXT , jp_compile ( "not_exist_key" ) )
95
107
self .assertEqual (matched_obj , (None , 'toml' ))
96
108
# test index out of range
97
- matched_obj = jsonfmt .parse_to_pyobj (YAML_TEXT , 'actions[7]' )
109
+ matched_obj = jsonfmt .parse_to_pyobj (YAML_TEXT , jp_compile ( 'actions[7]' ) )
98
110
self .assertEqual (matched_obj , (None , 'yaml' ))
99
111
100
112
# test empty jmespath
101
- with patch ('jsonfmt.stderr' , FakeStdErr ()), \
102
- self .assertRaises (jsonfmt .JMESPathError ):
103
- matched_obj = jsonfmt .parse_to_pyobj (JSON_TEXT , "" )
113
+ with patch ('jsonfmt.stderr' , FakeStdErr ()), self .assertRaises (jsonfmt .JMESPathError ):
114
+ matched_obj = jsonfmt .parse_to_pyobj (JSON_TEXT , jp_compile ("" ))
104
115
105
116
# test for unsupported format
106
117
with self .assertRaises (jsonfmt .FormatError ), open (__file__ ) as fp :
107
118
text = fp .read ()
108
- matched_obj = jsonfmt .parse_to_pyobj (text , "actions[0].calorie" )
119
+ matched_obj = jsonfmt .parse_to_pyobj (text , jp_compile ( "actions[0].calorie" ) )
109
120
110
121
def test_modify_pyobj_for_adding (self ):
111
122
# test empty sets and pops
@@ -297,7 +308,7 @@ def test_parse_cmdline_args(self):
297
308
self .assertEqual (actual_args , expected_args )
298
309
299
310
@patch .multiple (sys , argv = ['jsonfmt' , '-i' , 't' , '-p' , 'actions[*].name' ,
300
- f' { BASE_DIR } /test/example.json' ])
311
+ JSON_FILE ])
301
312
@patch .multiple (jsonfmt , stdout = FakeStdOut ())
302
313
def test_main_with_file (self ):
303
314
expected_output = color ('[\n \t "eat",\n \t "sport"\n ]' , 'json' )
@@ -311,97 +322,100 @@ def test_main_with_stdin(self):
311
322
jsonfmt .main ()
312
323
self .assertEqual (jsonfmt .stdout .read (), expected_output )
313
324
314
- @patch .multiple (sys , argv = ['jsonfmt' , 'not_exist_file.json' , __file__ ])
315
325
@patch .multiple (jsonfmt , stderr = FakeStdErr ())
316
- def test_main_invalid_file (self ):
317
- jsonfmt .main ()
318
- errmsg = jsonfmt .stderr .read ()
319
- self .assertIn ('no such file `not_exist_file.json`' , errmsg )
320
- self .assertIn ('no json, toml or yaml found' , errmsg )
321
-
322
- @patch .multiple (sys , argv = ['jsonfmt' , '-f' , 'json' ])
323
- @patch .multiple (jsonfmt , stdin = FakeStdIn (']a, b, c]' ), stderr = FakeStdErr ())
324
326
def test_main_invalid_input (self ):
325
- jsonfmt .main ()
326
- self .assertIn ('no json, toml or yaml found' , jsonfmt .stderr .read ())
327
+ # test not exist file and wrong format
328
+ with patch .multiple (sys , argv = ['jsonfmt' , 'not_exist_file.json' , __file__ ]):
329
+ jsonfmt .main ()
330
+ errmsg = jsonfmt .stderr .read ()
331
+ self .assertIn ('no such file: not_exist_file.json' , errmsg )
332
+ self .assertIn ('no json, toml or yaml found' , errmsg )
327
333
328
- @patch .multiple (sys , argv = ['jsonfmt' , '-f' , 'toml' ])
329
- @patch .multiple (jsonfmt , stdin = FakeStdIn (JSON_TEXT ), stdout = FakeStdOut ())
330
- def test_json_to_toml (self ):
331
- colored_output = color (TOML_TEXT , 'toml' )
332
- jsonfmt .main ()
333
- self .assertEqual (jsonfmt .stdout .read (), colored_output )
334
+ # test wrong jmespath
335
+ with patch ('sys.argv' , ['jsonfmt' , JSON_FILE , '-p' , '$.-[=]' ]),\
336
+ self .assertRaises (SystemExit ):
337
+ jsonfmt .main ()
338
+ self .assertIn ('invalid JMESPath expression' , jsonfmt .stderr .read ())
334
339
335
- @patch .multiple (sys , argv = ['jsonfmt' , '-s' , '-f' , 'yaml' ])
336
- @patch .multiple (jsonfmt , stdin = FakeStdIn (TOML_TEXT ), stdout = FakeStdOut ())
337
- def test_toml_to_yaml (self ):
338
- colored_output = color (YAML_TEXT , 'yaml' )
339
- jsonfmt .main ()
340
- self .assertEqual (jsonfmt .stdout .read (), colored_output )
340
+ @patch ('jsonfmt.stdout' , FakeStdOut ())
341
+ def test_main_convert (self ):
342
+ # test json to toml
343
+ with patch .multiple (sys , argv = ['jsonfmt' , '-f' , 'toml' , JSON_FILE ]):
344
+ colored_output = color (TOML_TEXT , 'toml' )
345
+ jsonfmt .main ()
346
+ self .assertEqual (jsonfmt .stdout .read (), colored_output )
347
+
348
+ # test toml to yaml
349
+ with patch .multiple (sys , argv = ['jsonfmt' , '-s' , '-f' , 'yaml' , TOML_FILE ]):
350
+ colored_output = color (YAML_TEXT , 'yaml' )
351
+ jsonfmt .main ()
352
+ self .assertEqual (jsonfmt .stdout .read (), colored_output )
353
+
354
+ # test yaml to json
355
+ with patch .multiple (sys , argv = ['jsonfmt' , '-c' , '-f' , 'json' , YAML_FILE ]):
356
+ colored_output = color (JSON_TEXT , 'json' )
357
+ jsonfmt .main ()
358
+ self .assertEqual (jsonfmt .stdout .read (), colored_output )
341
359
342
- @patch .multiple (sys , argv = ['jsonfmt' , '-c' , '-f' , 'json' ])
343
- @patch .multiple (jsonfmt , stdin = FakeStdIn (YAML_TEXT ), stdout = FakeStdOut ())
344
- def test_yaml_to_json (self ):
345
- colored_output = color (JSON_TEXT , 'json' )
360
+ @patch .multiple (sys , argv = ['jsonfmt' , '-oc' ])
361
+ @patch .multiple (jsonfmt , stdin = FakeStdIn ('{"a": "asfd", "b": [1, 2, 3]}' ), stdout = FakeStdOut (tty = False ))
362
+ def test_main_overview (self ):
346
363
jsonfmt .main ()
347
- self .assertEqual (jsonfmt .stdout .read (), colored_output )
364
+ self .assertEqual (jsonfmt .stdout .read (), '{"a":"...","b":[]}' )
348
365
349
- @patch .multiple (sys , argv = ['jsonfmt' , '-Ocsf' , 'json' ,
350
- f'{ BASE_DIR } /test/example.toml' ])
351
- def test_overwrite_to_original_file (self ):
366
+ @patch ('sys.argv' , ['jsonfmt' , '-Ocsf' , 'json' , TOML_FILE ])
367
+ def test_main_overwrite_to_original_file (self ):
352
368
try :
353
369
jsonfmt .main ()
354
- with open (f' { BASE_DIR } /test/example.toml' ) as toml_fp :
370
+ with open (TOML_FILE ) as toml_fp :
355
371
new_content = toml_fp .read ().strip ()
356
372
self .assertEqual (new_content , JSON_TEXT .strip ())
357
373
finally :
358
- with open (f' { BASE_DIR } /test/example.toml' , 'w' ) as toml_fp :
374
+ with open (TOML_FILE , 'w' ) as toml_fp :
359
375
toml_fp .write (TOML_TEXT )
360
376
361
377
@patch .multiple (jsonfmt , stdout = FakeStdOut (), stderr = FakeStdErr ())
362
- def test_copy_to_clipboard (self ):
378
+ def test_main_copy_to_clipboard (self ):
363
379
if jsonfmt .is_clipboard_available ():
364
380
with patch ("sys.argv" ,
365
- ['jsonfmt' , '-Ccs' , f' { BASE_DIR } /test/example.json' ]):
381
+ ['jsonfmt' , '-Ccs' , JSON_FILE ]):
366
382
jsonfmt .main ()
367
383
copied_text = pyperclip .paste ().strip ()
368
384
self .assertEqual (copied_text , JSON_TEXT .strip ())
369
385
370
386
with patch ("sys.argv" ,
371
- ['jsonfmt' , '-Cs' , f' { BASE_DIR } /test/example.toml' ]):
387
+ ['jsonfmt' , '-Cs' , TOML_FILE ]):
372
388
jsonfmt .main ()
373
389
copied_text = pyperclip .paste ().strip ()
374
390
self .assertEqual (copied_text , TOML_TEXT .strip ())
375
391
376
392
with patch ("sys.argv" ,
377
- ['jsonfmt' , '-Cs' , f' { BASE_DIR } /test/example.yaml' ]):
393
+ ['jsonfmt' , '-Cs' , YAML_FILE ]):
378
394
jsonfmt .main ()
379
395
copied_text = pyperclip .paste ().strip ()
380
396
self .assertEqual (copied_text , YAML_TEXT .strip ())
381
397
382
398
@patch .multiple (jsonfmt , is_clipboard_available = lambda : False )
383
399
@patch .multiple (jsonfmt , stdout = FakeStdOut (), stderr = FakeStdErr ())
384
- @patch .multiple (sys , argv = ['jsonfmt' , f' { BASE_DIR } /test/example.json' , '-cC' ])
385
- def test_clipboard_unavailable (self ):
400
+ @patch .multiple (sys , argv = ['jsonfmt' , JSON_FILE , '-cC' ])
401
+ def test_main_clipboard_unavailable (self ):
386
402
errmsg = '\033 [1;91mjsonfmt:\033 [0m \033 [0;91mclipboard unavailable\033 [0m\n '
387
403
jsonfmt .main ()
388
404
self .assertEqual (jsonfmt .stderr .read (), errmsg )
389
405
self .assertEqual (jsonfmt .stdout .read (), color (JSON_TEXT , 'json' ))
390
406
391
- @patch .multiple (sys , argv = ['jsonfmt' , '-O' , f'{ BASE_DIR } /test/example.json' ,
392
- '--set' , 'age=32; box=[1,2,3]' ,
393
- '--pop' , 'money; actions.1' ])
394
- def test_modify_and_pop (self ):
407
+ @patch .multiple (sys , argv = ['jsonfmt' , '--set' , 'age=32; box=[1,2,3]' , '--pop' , 'money; actions.1' ])
408
+ @patch .multiple (jsonfmt , stdin = FakeStdIn (JSON_TEXT ), stdout = FakeStdOut (tty = False ))
409
+ def test_main_modify_and_pop (self ):
395
410
try :
396
411
jsonfmt .main ()
397
- with open (f'{ BASE_DIR } /test/example.json' ) as fp :
398
- py_obj = json .load (fp )
412
+ py_obj = json .loads (jsonfmt .stdout .read ())
399
413
self .assertEqual (py_obj ['age' ], 32 )
400
414
self .assertEqual (py_obj ['box' ], [1 , 2 , 3 ])
401
415
self .assertNotIn ('money' , py_obj )
402
416
self .assertEqual (len (py_obj ['actions' ]), 1 )
403
417
finally :
404
- with open (f' { BASE_DIR } /test/example.json' , 'w' ) as fp :
418
+ with open (JSON_FILE , 'w' ) as fp :
405
419
fp .write (JSON_TEXT )
406
420
407
421
0 commit comments