moved trivialjson to a separate file
parent
c6306eb798
commit
e179aadfdf
|
@ -16,6 +16,11 @@ try:
|
||||||
import cStringIO as StringIO
|
import cStringIO as StringIO
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import StringIO
|
import StringIO
|
||||||
|
|
||||||
|
try:
|
||||||
|
import json
|
||||||
|
except ImportError: # Python <2.6, use trivialjson (https://github.com/phihag/trivialjson):
|
||||||
|
import trivialjson as json
|
||||||
|
|
||||||
std_headers = {
|
std_headers = {
|
||||||
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:5.0.1) Gecko/20100101 Firefox/5.0.1',
|
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:5.0.1) Gecko/20100101 Firefox/5.0.1',
|
||||||
|
@ -260,116 +265,3 @@ class YoutubeDLHandler(urllib2.HTTPHandler):
|
||||||
resp = self.addinfourl_wrapper(gz, old_resp.headers, old_resp.url, old_resp.code)
|
resp = self.addinfourl_wrapper(gz, old_resp.headers, old_resp.url, old_resp.code)
|
||||||
resp.msg = old_resp.msg
|
resp.msg = old_resp.msg
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
try:
|
|
||||||
import json
|
|
||||||
except ImportError: # Python <2.6, use trivialjson (https://github.com/phihag/trivialjson):
|
|
||||||
import re
|
|
||||||
class json(object):
|
|
||||||
@staticmethod
|
|
||||||
def loads(s):
|
|
||||||
s = s.decode('UTF-8')
|
|
||||||
def raiseError(msg, i):
|
|
||||||
raise ValueError(msg + ' at position ' + str(i) + ' of ' + repr(s) + ': ' + repr(s[i:]))
|
|
||||||
def skipSpace(i, expectMore=True):
|
|
||||||
while i < len(s) and s[i] in ' \t\r\n':
|
|
||||||
i += 1
|
|
||||||
if expectMore:
|
|
||||||
if i >= len(s):
|
|
||||||
raiseError('Premature end', i)
|
|
||||||
return i
|
|
||||||
def decodeEscape(match):
|
|
||||||
esc = match.group(1)
|
|
||||||
_STATIC = {
|
|
||||||
'"': '"',
|
|
||||||
'\\': '\\',
|
|
||||||
'/': '/',
|
|
||||||
'b': unichr(0x8),
|
|
||||||
'f': unichr(0xc),
|
|
||||||
'n': '\n',
|
|
||||||
'r': '\r',
|
|
||||||
't': '\t',
|
|
||||||
}
|
|
||||||
if esc in _STATIC:
|
|
||||||
return _STATIC[esc]
|
|
||||||
if esc[0] == 'u':
|
|
||||||
if len(esc) == 1+4:
|
|
||||||
return unichr(int(esc[1:5], 16))
|
|
||||||
if len(esc) == 5+6 and esc[5:7] == '\\u':
|
|
||||||
hi = int(esc[1:5], 16)
|
|
||||||
low = int(esc[7:11], 16)
|
|
||||||
return unichr((hi - 0xd800) * 0x400 + low - 0xdc00 + 0x10000)
|
|
||||||
raise ValueError('Unknown escape ' + str(esc))
|
|
||||||
def parseString(i):
|
|
||||||
i += 1
|
|
||||||
e = i
|
|
||||||
while True:
|
|
||||||
e = s.index('"', e)
|
|
||||||
bslashes = 0
|
|
||||||
while s[e-bslashes-1] == '\\':
|
|
||||||
bslashes += 1
|
|
||||||
if bslashes % 2 == 1:
|
|
||||||
e += 1
|
|
||||||
continue
|
|
||||||
break
|
|
||||||
rexp = re.compile(r'\\(u[dD][89aAbB][0-9a-fA-F]{2}\\u[0-9a-fA-F]{4}|u[0-9a-fA-F]{4}|.|$)')
|
|
||||||
stri = rexp.sub(decodeEscape, s[i:e])
|
|
||||||
return (e+1,stri)
|
|
||||||
def parseObj(i):
|
|
||||||
i += 1
|
|
||||||
res = {}
|
|
||||||
i = skipSpace(i)
|
|
||||||
if s[i] == '}': # Empty dictionary
|
|
||||||
return (i+1,res)
|
|
||||||
while True:
|
|
||||||
if s[i] != '"':
|
|
||||||
raiseError('Expected a string object key', i)
|
|
||||||
i,key = parseString(i)
|
|
||||||
i = skipSpace(i)
|
|
||||||
if i >= len(s) or s[i] != ':':
|
|
||||||
raiseError('Expected a colon', i)
|
|
||||||
i,val = parse(i+1)
|
|
||||||
res[key] = val
|
|
||||||
i = skipSpace(i)
|
|
||||||
if s[i] == '}':
|
|
||||||
return (i+1, res)
|
|
||||||
if s[i] != ',':
|
|
||||||
raiseError('Expected comma or closing curly brace', i)
|
|
||||||
i = skipSpace(i+1)
|
|
||||||
def parseArray(i):
|
|
||||||
res = []
|
|
||||||
i = skipSpace(i+1)
|
|
||||||
if s[i] == ']': # Empty array
|
|
||||||
return (i+1,res)
|
|
||||||
while True:
|
|
||||||
i,val = parse(i)
|
|
||||||
res.append(val)
|
|
||||||
i = skipSpace(i) # Raise exception if premature end
|
|
||||||
if s[i] == ']':
|
|
||||||
return (i+1, res)
|
|
||||||
if s[i] != ',':
|
|
||||||
raiseError('Expected a comma or closing bracket', i)
|
|
||||||
i = skipSpace(i+1)
|
|
||||||
def parseDiscrete(i):
|
|
||||||
for k,v in {'true': True, 'false': False, 'null': None}.items():
|
|
||||||
if s.startswith(k, i):
|
|
||||||
return (i+len(k), v)
|
|
||||||
raiseError('Not a boolean (or null)', i)
|
|
||||||
def parseNumber(i):
|
|
||||||
mobj = re.match('^(-?(0|[1-9][0-9]*)(\.[0-9]*)?([eE][+-]?[0-9]+)?)', s[i:])
|
|
||||||
if mobj is None:
|
|
||||||
raiseError('Not a number', i)
|
|
||||||
nums = mobj.group(1)
|
|
||||||
if '.' in nums or 'e' in nums or 'E' in nums:
|
|
||||||
return (i+len(nums), float(nums))
|
|
||||||
return (i+len(nums), int(nums))
|
|
||||||
CHARMAP = {'{': parseObj, '[': parseArray, '"': parseString, 't': parseDiscrete, 'f': parseDiscrete, 'n': parseDiscrete}
|
|
||||||
def parse(i):
|
|
||||||
i = skipSpace(i)
|
|
||||||
i,res = CHARMAP.get(s[i], parseNumber)(i)
|
|
||||||
i = skipSpace(i, False)
|
|
||||||
return (i,res)
|
|
||||||
i,res = parse(0)
|
|
||||||
if i < len(s):
|
|
||||||
raise ValueError('Extra data at end of input (index ' + str(i) + ' of ' + repr(s) + ': ' + repr(s[i:]) + ')')
|
|
||||||
return res
|
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
"""trivialjson (https://github.com/phihag/trivialjson)"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
def loads(s):
|
||||||
|
s = s.decode('UTF-8')
|
||||||
|
def raiseError(msg, i):
|
||||||
|
raise ValueError(msg + ' at position ' + str(i) + ' of ' + repr(s) + ': ' + repr(s[i:]))
|
||||||
|
def skipSpace(i, expectMore=True):
|
||||||
|
while i < len(s) and s[i] in ' \t\r\n':
|
||||||
|
i += 1
|
||||||
|
if expectMore:
|
||||||
|
if i >= len(s):
|
||||||
|
raiseError('Premature end', i)
|
||||||
|
return i
|
||||||
|
def decodeEscape(match):
|
||||||
|
esc = match.group(1)
|
||||||
|
_STATIC = {
|
||||||
|
'"': '"',
|
||||||
|
'\\': '\\',
|
||||||
|
'/': '/',
|
||||||
|
'b': unichr(0x8),
|
||||||
|
'f': unichr(0xc),
|
||||||
|
'n': '\n',
|
||||||
|
'r': '\r',
|
||||||
|
't': '\t',
|
||||||
|
}
|
||||||
|
if esc in _STATIC:
|
||||||
|
return _STATIC[esc]
|
||||||
|
if esc[0] == 'u':
|
||||||
|
if len(esc) == 1+4:
|
||||||
|
return unichr(int(esc[1:5], 16))
|
||||||
|
if len(esc) == 5+6 and esc[5:7] == '\\u':
|
||||||
|
hi = int(esc[1:5], 16)
|
||||||
|
low = int(esc[7:11], 16)
|
||||||
|
return unichr((hi - 0xd800) * 0x400 + low - 0xdc00 + 0x10000)
|
||||||
|
raise ValueError('Unknown escape ' + str(esc))
|
||||||
|
def parseString(i):
|
||||||
|
i += 1
|
||||||
|
e = i
|
||||||
|
while True:
|
||||||
|
e = s.index('"', e)
|
||||||
|
bslashes = 0
|
||||||
|
while s[e-bslashes-1] == '\\':
|
||||||
|
bslashes += 1
|
||||||
|
if bslashes % 2 == 1:
|
||||||
|
e += 1
|
||||||
|
continue
|
||||||
|
break
|
||||||
|
rexp = re.compile(r'\\(u[dD][89aAbB][0-9a-fA-F]{2}\\u[0-9a-fA-F]{4}|u[0-9a-fA-F]{4}|.|$)')
|
||||||
|
stri = rexp.sub(decodeEscape, s[i:e])
|
||||||
|
return (e+1,stri)
|
||||||
|
def parseObj(i):
|
||||||
|
i += 1
|
||||||
|
res = {}
|
||||||
|
i = skipSpace(i)
|
||||||
|
if s[i] == '}': # Empty dictionary
|
||||||
|
return (i+1,res)
|
||||||
|
while True:
|
||||||
|
if s[i] != '"':
|
||||||
|
raiseError('Expected a string object key', i)
|
||||||
|
i,key = parseString(i)
|
||||||
|
i = skipSpace(i)
|
||||||
|
if i >= len(s) or s[i] != ':':
|
||||||
|
raiseError('Expected a colon', i)
|
||||||
|
i,val = parse(i+1)
|
||||||
|
res[key] = val
|
||||||
|
i = skipSpace(i)
|
||||||
|
if s[i] == '}':
|
||||||
|
return (i+1, res)
|
||||||
|
if s[i] != ',':
|
||||||
|
raiseError('Expected comma or closing curly brace', i)
|
||||||
|
i = skipSpace(i+1)
|
||||||
|
def parseArray(i):
|
||||||
|
res = []
|
||||||
|
i = skipSpace(i+1)
|
||||||
|
if s[i] == ']': # Empty array
|
||||||
|
return (i+1,res)
|
||||||
|
while True:
|
||||||
|
i,val = parse(i)
|
||||||
|
res.append(val)
|
||||||
|
i = skipSpace(i) # Raise exception if premature end
|
||||||
|
if s[i] == ']':
|
||||||
|
return (i+1, res)
|
||||||
|
if s[i] != ',':
|
||||||
|
raiseError('Expected a comma or closing bracket', i)
|
||||||
|
i = skipSpace(i+1)
|
||||||
|
def parseDiscrete(i):
|
||||||
|
for k,v in {'true': True, 'false': False, 'null': None}.items():
|
||||||
|
if s.startswith(k, i):
|
||||||
|
return (i+len(k), v)
|
||||||
|
raiseError('Not a boolean (or null)', i)
|
||||||
|
def parseNumber(i):
|
||||||
|
mobj = re.match('^(-?(0|[1-9][0-9]*)(\.[0-9]*)?([eE][+-]?[0-9]+)?)', s[i:])
|
||||||
|
if mobj is None:
|
||||||
|
raiseError('Not a number', i)
|
||||||
|
nums = mobj.group(1)
|
||||||
|
if '.' in nums or 'e' in nums or 'E' in nums:
|
||||||
|
return (i+len(nums), float(nums))
|
||||||
|
return (i+len(nums), int(nums))
|
||||||
|
CHARMAP = {'{': parseObj, '[': parseArray, '"': parseString, 't': parseDiscrete, 'f': parseDiscrete, 'n': parseDiscrete}
|
||||||
|
def parse(i):
|
||||||
|
i = skipSpace(i)
|
||||||
|
i,res = CHARMAP.get(s[i], parseNumber)(i)
|
||||||
|
i = skipSpace(i, False)
|
||||||
|
return (i,res)
|
||||||
|
i,res = parse(0)
|
||||||
|
if i < len(s):
|
||||||
|
raise ValueError('Extra data at end of input (index ' + str(i) + ' of ' + repr(s) + ': ' + repr(s[i:]) + ')')
|
||||||
|
return res
|
Loading…
Reference in New Issue