jsonpointer 3.2.1__tar.gz → 3.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {jsonpointer-3.2.1/jsonpointer.egg-info → jsonpointer-3.3}/PKG-INFO +1 -1
- {jsonpointer-3.2.1 → jsonpointer-3.3}/bin/jsonpointer +14 -3
- {jsonpointer-3.2.1 → jsonpointer-3.3/jsonpointer.egg-info}/PKG-INFO +1 -1
- {jsonpointer-3.2.1 → jsonpointer-3.3}/jsonpointer.py +2 -2
- {jsonpointer-3.2.1 → jsonpointer-3.3}/tests.py +100 -1
- {jsonpointer-3.2.1 → jsonpointer-3.3}/AUTHORS +0 -0
- {jsonpointer-3.2.1 → jsonpointer-3.3}/LICENSE.txt +0 -0
- {jsonpointer-3.2.1 → jsonpointer-3.3}/MANIFEST.in +0 -0
- {jsonpointer-3.2.1 → jsonpointer-3.3}/README.md +0 -0
- {jsonpointer-3.2.1 → jsonpointer-3.3}/jsonpointer.egg-info/SOURCES.txt +0 -0
- {jsonpointer-3.2.1 → jsonpointer-3.3}/jsonpointer.egg-info/dependency_links.txt +0 -0
- {jsonpointer-3.2.1 → jsonpointer-3.3}/jsonpointer.egg-info/top_level.txt +0 -0
- {jsonpointer-3.2.1 → jsonpointer-3.3}/setup.cfg +0 -0
- {jsonpointer-3.2.1 → jsonpointer-3.3}/setup.py +0 -0
|
@@ -27,6 +27,8 @@ parser.add_argument('FILE', type=str, nargs='+',
|
|
|
27
27
|
help='Files for which the pointer should be resolved')
|
|
28
28
|
parser.add_argument('--indent', type=int, default=None,
|
|
29
29
|
help='Indent output by n spaces')
|
|
30
|
+
parser.add_argument('--continue-on-error', action='store_true',
|
|
31
|
+
help='Continue with remaining files after JSON or text decoding errors')
|
|
30
32
|
parser.add_argument('-v', '--version', action='version',
|
|
31
33
|
version='%(prog)s ' + jsonpointer.__version__)
|
|
32
34
|
|
|
@@ -77,8 +79,8 @@ def parse_pointer(args):
|
|
|
77
79
|
def resolve_files():
|
|
78
80
|
""" Resolve a JSON pointer on JSON files
|
|
79
81
|
|
|
80
|
-
Returns False if the pointer could not be resolved on at least one
|
|
81
|
-
|
|
82
|
+
Returns False if the pointer could not be resolved on at least one file,
|
|
83
|
+
or if --continue-on-error skipped a JSON or text decoding error. """
|
|
82
84
|
args = parser.parse_args()
|
|
83
85
|
|
|
84
86
|
ptr, files = parse_pointer(args)
|
|
@@ -90,7 +92,16 @@ def resolve_files():
|
|
|
90
92
|
except argparse.ArgumentTypeError as e:
|
|
91
93
|
parser.error(str(e))
|
|
92
94
|
|
|
93
|
-
|
|
95
|
+
try:
|
|
96
|
+
doc = json.load(f)
|
|
97
|
+
except (json.JSONDecodeError, UnicodeDecodeError) as e:
|
|
98
|
+
if not args.continue_on_error:
|
|
99
|
+
raise
|
|
100
|
+
print('Could not parse JSON in %r: %s' % (name, e),
|
|
101
|
+
file=sys.stderr)
|
|
102
|
+
ok = False
|
|
103
|
+
continue
|
|
104
|
+
|
|
94
105
|
try:
|
|
95
106
|
result = jsonpointer.resolve_pointer(doc, ptr)
|
|
96
107
|
print(json.dumps(result, indent=args.indent))
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
|
|
33
33
|
# Will be parsed by setup.py to determine package metadata
|
|
34
34
|
__author__ = 'Stefan Kögl <stefan@skoegl.net>'
|
|
35
|
-
__version__ = '3.
|
|
35
|
+
__version__ = '3.3'
|
|
36
36
|
__website__ = 'https://github.com/stefankoegl/python-json-pointer'
|
|
37
37
|
__license__ = 'Modified BSD License'
|
|
38
38
|
|
|
@@ -307,7 +307,7 @@ class JsonPointer:
|
|
|
307
307
|
suffix_parts = suffix
|
|
308
308
|
try:
|
|
309
309
|
return self.__class__.from_parts(chain(self.parts, suffix_parts))
|
|
310
|
-
except:
|
|
310
|
+
except Exception:
|
|
311
311
|
raise JsonPointerException("Invalid suffix")
|
|
312
312
|
|
|
313
313
|
def __truediv__(self, suffix):
|
|
@@ -196,6 +196,19 @@ class ComparisonTests(unittest.TestCase):
|
|
|
196
196
|
ptr12e = self.ptr1 / ["a", "b"]
|
|
197
197
|
self.assertEqual(ptr12e.path, "/a/b/c/a/b")
|
|
198
198
|
|
|
199
|
+
def test_join_preserves_control_flow_exceptions(self):
|
|
200
|
+
for exception_type in (KeyboardInterrupt, SystemExit, GeneratorExit):
|
|
201
|
+
with self.subTest(exception_type=exception_type):
|
|
202
|
+
error = exception_type()
|
|
203
|
+
|
|
204
|
+
def parts():
|
|
205
|
+
yield 'valid'
|
|
206
|
+
raise error
|
|
207
|
+
|
|
208
|
+
with self.assertRaises(exception_type) as caught:
|
|
209
|
+
self.ptr1.join(parts())
|
|
210
|
+
self.assertIs(caught.exception, error)
|
|
211
|
+
|
|
199
212
|
def test_join_subclass(self):
|
|
200
213
|
class Pointer(JsonPointer):
|
|
201
214
|
pass
|
|
@@ -494,7 +507,7 @@ class CommandLineTests(unittest.TestCase):
|
|
|
494
507
|
f.write(content)
|
|
495
508
|
|
|
496
509
|
def _run(self, *args):
|
|
497
|
-
env = dict(os.environ, PYTHONPATH=self.ROOT)
|
|
510
|
+
env = dict(os.environ, PYTHONPATH=self.ROOT, PYTHONUTF8='1')
|
|
498
511
|
return subprocess.run([sys.executable, self.SCRIPT] + list(args),
|
|
499
512
|
cwd=self.dir, env=env, capture_output=True,
|
|
500
513
|
text=True)
|
|
@@ -571,6 +584,92 @@ class CommandLineTests(unittest.TestCase):
|
|
|
571
584
|
self.assertIn('Could not resolve pointer', proc.stderr)
|
|
572
585
|
self.assertEqual(proc.stdout, '1\n')
|
|
573
586
|
|
|
587
|
+
def test_invalid_json(self):
|
|
588
|
+
for content in ('', '{"a": }', '{"a": 1}\n{"a": 2}'):
|
|
589
|
+
with self.subTest(content=content):
|
|
590
|
+
self._write('invalid.json', content)
|
|
591
|
+
proc = self._run('--continue-on-error', '/a', 'invalid.json')
|
|
592
|
+
self.assertEqual(proc.returncode, 1)
|
|
593
|
+
self.assertEqual(proc.stdout, '')
|
|
594
|
+
self.assertIn("Could not parse JSON in 'invalid.json':",
|
|
595
|
+
proc.stderr)
|
|
596
|
+
self.assertIn('line ', proc.stderr)
|
|
597
|
+
self.assertNotIn('Traceback', proc.stderr)
|
|
598
|
+
|
|
599
|
+
def test_invalid_json_in_one_file(self):
|
|
600
|
+
self._write('invalid.json', '{"a": }')
|
|
601
|
+
for index in range(3):
|
|
602
|
+
with self.subTest(index=index):
|
|
603
|
+
files = ['a.json', 'b.json']
|
|
604
|
+
files.insert(index, 'invalid.json')
|
|
605
|
+
proc = self._run('--continue-on-error', '/a', *files)
|
|
606
|
+
self.assertEqual(proc.returncode, 1)
|
|
607
|
+
self.assertEqual(proc.stdout, self.A_OUT + self.B_OUT)
|
|
608
|
+
self.assertIn("Could not parse JSON in 'invalid.json':",
|
|
609
|
+
proc.stderr)
|
|
610
|
+
self.assertNotIn('Traceback', proc.stderr)
|
|
611
|
+
|
|
612
|
+
def test_invalid_json_and_unresolvable_pointer(self):
|
|
613
|
+
self._write('invalid.json', '{"a": }')
|
|
614
|
+
proc = self._run('--continue-on-error', '/b',
|
|
615
|
+
'invalid.json', 'a.json', 'b.json')
|
|
616
|
+
self.assertEqual(proc.returncode, 1)
|
|
617
|
+
self.assertEqual(proc.stdout, '1\n')
|
|
618
|
+
self.assertIn("Could not parse JSON in 'invalid.json':", proc.stderr)
|
|
619
|
+
self.assertIn('Could not resolve pointer:', proc.stderr)
|
|
620
|
+
self.assertNotIn('Traceback', proc.stderr)
|
|
621
|
+
|
|
622
|
+
def test_invalid_json_stops_without_continue_on_error(self):
|
|
623
|
+
self._write('invalid.json', '{"a": }')
|
|
624
|
+
for index in range(3):
|
|
625
|
+
with self.subTest(index=index):
|
|
626
|
+
files = ['a.json', 'b.json']
|
|
627
|
+
files.insert(index, 'invalid.json')
|
|
628
|
+
proc = self._run('/a', *files)
|
|
629
|
+
self.assertEqual(proc.returncode, 1)
|
|
630
|
+
self.assertEqual(proc.stdout,
|
|
631
|
+
''.join([self.A_OUT, self.B_OUT][:index]))
|
|
632
|
+
self.assertIn('JSONDecodeError', proc.stderr)
|
|
633
|
+
|
|
634
|
+
def test_invalid_encoding_in_one_file(self):
|
|
635
|
+
with open(os.path.join(self.dir, 'invalid.json'), 'wb') as f:
|
|
636
|
+
f.write(b'{"a":"\xff"}')
|
|
637
|
+
for index in range(3):
|
|
638
|
+
with self.subTest(index=index):
|
|
639
|
+
files = ['a.json', 'b.json']
|
|
640
|
+
files.insert(index, 'invalid.json')
|
|
641
|
+
proc = self._run('--continue-on-error', '/a', *files)
|
|
642
|
+
self.assertEqual(proc.returncode, 1)
|
|
643
|
+
self.assertEqual(proc.stdout, self.A_OUT + self.B_OUT)
|
|
644
|
+
self.assertIn("Could not parse JSON in 'invalid.json':",
|
|
645
|
+
proc.stderr)
|
|
646
|
+
self.assertIn('decode', proc.stderr)
|
|
647
|
+
self.assertNotIn('Traceback', proc.stderr)
|
|
648
|
+
|
|
649
|
+
def test_invalid_encoding_stops_without_continue_on_error(self):
|
|
650
|
+
with open(os.path.join(self.dir, 'invalid.json'), 'wb') as f:
|
|
651
|
+
f.write(b'{"a":"\xff"}')
|
|
652
|
+
proc = self._run('/a', 'a.json', 'invalid.json', 'b.json')
|
|
653
|
+
self.assertEqual(proc.returncode, 1)
|
|
654
|
+
self.assertEqual(proc.stdout, self.A_OUT)
|
|
655
|
+
self.assertIn('UnicodeDecodeError', proc.stderr)
|
|
656
|
+
|
|
657
|
+
def test_continue_on_error_with_valid_files(self):
|
|
658
|
+
for pointer in (['/a'], ['-p', '/a'], ['-f', 'ptr.txt']):
|
|
659
|
+
with self.subTest(pointer=pointer):
|
|
660
|
+
proc = self._run('--continue-on-error', *pointer,
|
|
661
|
+
'a.json', 'b.json')
|
|
662
|
+
self.assertEqual(proc.returncode, 0, proc.stderr)
|
|
663
|
+
self.assertEqual(proc.stdout, self.A_OUT + self.B_OUT)
|
|
664
|
+
self.assertEqual(proc.stderr, '')
|
|
665
|
+
|
|
666
|
+
def test_continue_on_error_does_not_skip_missing_files(self):
|
|
667
|
+
proc = self._run('--continue-on-error', '/a',
|
|
668
|
+
'a.json', 'missing.json', 'b.json')
|
|
669
|
+
self.assertEqual(proc.returncode, 2)
|
|
670
|
+
self.assertEqual(proc.stdout, self.A_OUT)
|
|
671
|
+
self.assertIn('missing.json', proc.stderr)
|
|
672
|
+
|
|
574
673
|
def test_pointer_file_requires_value(self):
|
|
575
674
|
proc = self._run('-f', '-p', '/a', 'a.json')
|
|
576
675
|
self.assertEqual(proc.returncode, 2)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|