Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(63431)

Delta Between Two Patch Sets: Lib/json/decoder.py

Issue 19361: Specialize exceptions thrown by JSON parser
Left Patch Set: Created 5 years ago
Right Patch Set: Created 4 years, 10 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Doc/library/json.rst ('k') | Lib/json/__init__.py » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 """Implementation of JSONDecoder 1 """Implementation of JSONDecoder
2 """ 2 """
3 import re 3 import re
4 4
5 from json import scanner 5 from json import scanner
6 try: 6 try:
7 from _json import scanstring as c_scanstring 7 from _json import scanstring as c_scanstring
8 except ImportError: 8 except ImportError:
9 c_scanstring = None 9 c_scanstring = None
10 10
11 __all__ = ['JSONDecoder'] 11 __all__ = ['JSONDecoder', 'JSONDecodeError']
12 12
13 FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL 13 FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL
14 14
15 NaN = float('nan') 15 NaN = float('nan')
16 PosInf = float('inf') 16 PosInf = float('inf')
17 NegInf = float('-inf') 17 NegInf = float('-inf')
18 18
19 19
20 class JSONDecodeError(ValueError): 20 class JSONDecodeError(ValueError):
21 """Subclass of ValueError with the following additional properties: 21 """Subclass of ValueError with the following additional properties:
22 22
23 msg: The unformatted error message 23 msg: The unformatted error message
24 doc: The JSON document being parsed 24 doc: The JSON document being parsed
25 pos: The start index of doc where parsing failed 25 pos: The start index of doc where parsing failed
26 end: The end index of doc where parsing failed (may be None)
27 lineno: The line corresponding to pos 26 lineno: The line corresponding to pos
28 colno: The column corresponding to pos 27 colno: The column corresponding to pos
29 endlineno: The line corresponding to end (may be None)
30 endcolno: The column corresponding to end (may be None)
31 28
32 """ 29 """
33 # Note that this exception is used from _json 30 # Note that this exception is used from _json
34 def __init__(self, msg, doc, pos, end=None): 31 def __init__(self, msg, doc, pos):
35 ValueError.__init__(self, errmsg(msg, doc, pos, end=end)) 32 lineno = doc.count('\n', 0, pos) + 1
33 colno = pos - doc.rfind('\n', 0, pos)
34 errmsg = '%s: line %d column %d (char %d)' % (msg, lineno, colno, pos)
35 ValueError.__init__(self, errmsg)
36 self.msg = msg 36 self.msg = msg
37 self.doc = doc 37 self.doc = doc
38 self.pos = pos 38 self.pos = pos
39 self.end = end 39 self.lineno = lineno
40 self.lineno, self.colno = linecol(doc, pos) 40 self.colno = colno
41 if end is not None:
42 self.endlineno, self.endcolno = linecol(doc, end)
43 else:
44 self.endlineno, self.endcolno = None, None
45 41
46 def __reduce__(self): 42 def __reduce__(self):
47 return self.__class__, (self.msg, self.doc, self.pos, self.end) 43 return self.__class__, (self.msg, self.doc, self.pos)
48
49
50 def linecol(doc, pos):
51 if isinstance(doc, bytes):
52 newline = b'\n'
53 else:
54 newline = '\n'
55 lineno = doc.count(newline, 0, pos) + 1
56 if lineno == 1:
57 colno = pos + 1
58 else:
59 colno = pos - doc.rindex(newline, 0, pos)
60 return lineno, colno
61
62
63 def errmsg(msg, doc, pos, end=None):
64 lineno, colno = linecol(doc, pos)
65 if end is None:
66 fmt = '{0}: line {1} column {2} (char {3})'
67 return fmt.format(msg, lineno, colno, pos)
68 #fmt = '%s: line %d column %d (char %d)'
69 #return fmt % (msg, lineno, colno, pos)
70 endlineno, endcolno = linecol(doc, end)
71 fmt = '{0}: line {1} column {2} - line {3} column {4} (char {5} - {6})'
72 return fmt.format(msg, lineno, colno, endlineno, endcolno, pos, end)
73 #fmt = '%s: line %d column %d - line %d column %d (char %d - %d)'
74 #return fmt % (msg, lineno, colno, endlineno, endcolno, pos, end)
75 44
76 45
77 _CONSTANTS = { 46 _CONSTANTS = {
78 '-Infinity': NegInf, 47 '-Infinity': NegInf,
79 'Infinity': PosInf, 48 'Infinity': PosInf,
80 'NaN': NaN, 49 'NaN': NaN,
81 } 50 }
82 51
83 52
84 STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS) 53 STRINGCHUNK = re.compile(r'(.*?)(["\\\x00-\x1f])', FLAGS)
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 332
364 333
365 def decode(self, s, _w=WHITESPACE.match): 334 def decode(self, s, _w=WHITESPACE.match):
366 """Return the Python representation of ``s`` (a ``str`` instance 335 """Return the Python representation of ``s`` (a ``str`` instance
367 containing a JSON document). 336 containing a JSON document).
368 337
369 """ 338 """
370 obj, end = self.raw_decode(s, idx=_w(s, 0).end()) 339 obj, end = self.raw_decode(s, idx=_w(s, 0).end())
371 end = _w(s, end).end() 340 end = _w(s, end).end()
372 if end != len(s): 341 if end != len(s):
373 raise JSONDecodeError("Extra data", s, end, len(s)) 342 raise JSONDecodeError("Extra data", s, end)
374 return obj 343 return obj
375 344
376 def raw_decode(self, s, idx=0): 345 def raw_decode(self, s, idx=0):
377 """Decode a JSON document from ``s`` (a ``str`` beginning with 346 """Decode a JSON document from ``s`` (a ``str`` beginning with
378 a JSON document) and return a 2-tuple of the Python 347 a JSON document) and return a 2-tuple of the Python
379 representation and the index in ``s`` where the document ended. 348 representation and the index in ``s`` where the document ended.
380 349
381 This can be used to decode a JSON document from a string that may 350 This can be used to decode a JSON document from a string that may
382 have extraneous data at the end. 351 have extraneous data at the end.
383 352
384 """ 353 """
385 try: 354 try:
386 obj, end = self.scan_once(s, idx) 355 obj, end = self.scan_once(s, idx)
387 except StopIteration as err: 356 except StopIteration as err:
388 raise JSONDecodeError("Expecting value", s, err.value) from None 357 raise JSONDecodeError("Expecting value", s, err.value) from None
389 return obj, end 358 return obj, end
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+