Skip to content

Commit

Permalink
Added simplejson
Browse files Browse the repository at this point in the history
  • Loading branch information
greghaynes committed May 28, 2010
1 parent cf87d65 commit a8f9efe
Show file tree
Hide file tree
Showing 41 changed files with 5,082 additions and 0 deletions.
Binary file added src/pyscripts/simplejson/.__speedups.c
Binary file not shown.
Binary file added src/pyscripts/simplejson/._decoder.py
Binary file not shown.
Binary file added src/pyscripts/simplejson/._encoder.py
Binary file not shown.
Binary file added src/pyscripts/simplejson/._ordered_dict.py
Binary file not shown.
Binary file added src/pyscripts/simplejson/._scanner.py
Binary file not shown.
Binary file added src/pyscripts/simplejson/._tool.py
Binary file not shown.
437 changes: 437 additions & 0 deletions src/pyscripts/simplejson/__init__.py

Large diffs are not rendered by default.

2,561 changes: 2,561 additions & 0 deletions src/pyscripts/simplejson/_speedups.c

Large diffs are not rendered by default.

421 changes: 421 additions & 0 deletions src/pyscripts/simplejson/decoder.py

Large diffs are not rendered by default.

501 changes: 501 additions & 0 deletions src/pyscripts/simplejson/encoder.py

Large diffs are not rendered by default.

119 changes: 119 additions & 0 deletions src/pyscripts/simplejson/ordered_dict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
"""Drop-in replacement for collections.OrderedDict by Raymond Hettinger
http://code.activestate.com/recipes/576693/
"""
from UserDict import DictMixin

# Modified from original to support Python 2.4, see
# http://code.google.com/p/simplejson/issues/detail?id=53
try:
all
except NameError:
def all(seq):
for elem in seq:
if not elem:
return False
return True

class OrderedDict(dict, DictMixin):

def __init__(self, *args, **kwds):
if len(args) > 1:
raise TypeError('expected at most 1 arguments, got %d' % len(args))
try:
self.__end
except AttributeError:
self.clear()
self.update(*args, **kwds)

def clear(self):
self.__end = end = []
end += [None, end, end] # sentinel node for doubly linked list
self.__map = {} # key --> [key, prev, next]
dict.clear(self)

def __setitem__(self, key, value):
if key not in self:
end = self.__end
curr = end[1]
curr[2] = end[1] = self.__map[key] = [key, curr, end]
dict.__setitem__(self, key, value)

def __delitem__(self, key):
dict.__delitem__(self, key)
key, prev, next = self.__map.pop(key)
prev[2] = next
next[1] = prev

def __iter__(self):
end = self.__end
curr = end[2]
while curr is not end:
yield curr[0]
curr = curr[2]

def __reversed__(self):
end = self.__end
curr = end[1]
while curr is not end:
yield curr[0]
curr = curr[1]

def popitem(self, last=True):
if not self:
raise KeyError('dictionary is empty')
# Modified from original to support Python 2.4, see
# http://code.google.com/p/simplejson/issues/detail?id=53
if last:
key = reversed(self).next()
else:
key = iter(self).next()
value = self.pop(key)
return key, value

def __reduce__(self):
items = [[k, self[k]] for k in self]
tmp = self.__map, self.__end
del self.__map, self.__end
inst_dict = vars(self).copy()
self.__map, self.__end = tmp
if inst_dict:
return (self.__class__, (items,), inst_dict)
return self.__class__, (items,)

def keys(self):
return list(self)

setdefault = DictMixin.setdefault
update = DictMixin.update
pop = DictMixin.pop
values = DictMixin.values
items = DictMixin.items
iterkeys = DictMixin.iterkeys
itervalues = DictMixin.itervalues
iteritems = DictMixin.iteritems

def __repr__(self):
if not self:
return '%s()' % (self.__class__.__name__,)
return '%s(%r)' % (self.__class__.__name__, self.items())

def copy(self):
return self.__class__(self)

@classmethod
def fromkeys(cls, iterable, value=None):
d = cls()
for key in iterable:
d[key] = value
return d

def __eq__(self, other):
if isinstance(other, OrderedDict):
return len(self)==len(other) and \
all(p==q for p, q in zip(self.items(), other.items()))
return dict.__eq__(self, other)

def __ne__(self, other):
return not self == other
77 changes: 77 additions & 0 deletions src/pyscripts/simplejson/scanner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"""JSON token scanner
"""
import re
def _import_c_make_scanner():
try:
from simplejson._speedups import make_scanner
return make_scanner
except ImportError:
return None
c_make_scanner = _import_c_make_scanner()

__all__ = ['make_scanner']

NUMBER_RE = re.compile(
r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?',
(re.VERBOSE | re.MULTILINE | re.DOTALL))

def py_make_scanner(context):
parse_object = context.parse_object
parse_array = context.parse_array
parse_string = context.parse_string
match_number = NUMBER_RE.match
encoding = context.encoding
strict = context.strict
parse_float = context.parse_float
parse_int = context.parse_int
parse_constant = context.parse_constant
object_hook = context.object_hook
object_pairs_hook = context.object_pairs_hook
memo = context.memo

def _scan_once(string, idx):
try:
nextchar = string[idx]
except IndexError:
raise StopIteration

if nextchar == '"':
return parse_string(string, idx + 1, encoding, strict)
elif nextchar == '{':
return parse_object((string, idx + 1), encoding, strict,
_scan_once, object_hook, object_pairs_hook, memo)
elif nextchar == '[':
return parse_array((string, idx + 1), _scan_once)
elif nextchar == 'n' and string[idx:idx + 4] == 'null':
return None, idx + 4
elif nextchar == 't' and string[idx:idx + 4] == 'true':
return True, idx + 4
elif nextchar == 'f' and string[idx:idx + 5] == 'false':
return False, idx + 5

m = match_number(string, idx)
if m is not None:
integer, frac, exp = m.groups()
if frac or exp:
res = parse_float(integer + (frac or '') + (exp or ''))
else:
res = parse_int(integer)
return res, m.end()
elif nextchar == 'N' and string[idx:idx + 3] == 'NaN':
return parse_constant('NaN'), idx + 3
elif nextchar == 'I' and string[idx:idx + 8] == 'Infinity':
return parse_constant('Infinity'), idx + 8
elif nextchar == '-' and string[idx:idx + 9] == '-Infinity':
return parse_constant('-Infinity'), idx + 9
else:
raise StopIteration

def scan_once(string, idx):
try:
return _scan_once(string, idx)
finally:
memo.clear()

return scan_once

make_scanner = c_make_scanner or py_make_scanner
Binary file added src/pyscripts/simplejson/tests/.___init__.py
Binary file not shown.
Binary file added src/pyscripts/simplejson/tests/._test_decimal.py
Binary file not shown.
Binary file added src/pyscripts/simplejson/tests/._test_decode.py
Binary file not shown.
Binary file added src/pyscripts/simplejson/tests/._test_default.py
Binary file not shown.
Binary file added src/pyscripts/simplejson/tests/._test_dump.py
Binary file not shown.
Binary file not shown.
Binary file added src/pyscripts/simplejson/tests/._test_float.py
Binary file not shown.
Binary file added src/pyscripts/simplejson/tests/._test_separators.py
Binary file not shown.
Binary file added src/pyscripts/simplejson/tests/._test_unicode.py
Binary file not shown.
63 changes: 63 additions & 0 deletions src/pyscripts/simplejson/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import unittest
import doctest


class OptionalExtensionTestSuite(unittest.TestSuite):
def run(self, result):
import simplejson
run = unittest.TestSuite.run
run(self, result)
simplejson._toggle_speedups(False)
run(self, result)
simplejson._toggle_speedups(True)
return result


def additional_tests(suite=None):
import simplejson
import simplejson.encoder
import simplejson.decoder
if suite is None:
suite = unittest.TestSuite()
for mod in (simplejson, simplejson.encoder, simplejson.decoder):
suite.addTest(doctest.DocTestSuite(mod))
suite.addTest(doctest.DocFileSuite('../../index.rst'))
return suite


def all_tests_suite():
suite = unittest.TestLoader().loadTestsFromNames([
'simplejson.tests.test_check_circular',
'simplejson.tests.test_decode',
'simplejson.tests.test_default',
'simplejson.tests.test_dump',
'simplejson.tests.test_encode_basestring_ascii',
'simplejson.tests.test_encode_for_html',
'simplejson.tests.test_fail',
'simplejson.tests.test_float',
'simplejson.tests.test_indent',
'simplejson.tests.test_pass1',
'simplejson.tests.test_pass2',
'simplejson.tests.test_pass3',
'simplejson.tests.test_recursion',
'simplejson.tests.test_scanstring',
'simplejson.tests.test_separators',
'simplejson.tests.test_speedups',
'simplejson.tests.test_unicode',
'simplejson.tests.test_decimal',
])
suite = additional_tests(suite)
return OptionalExtensionTestSuite([suite])


def main():
runner = unittest.TextTestRunner()
suite = all_tests_suite()
runner.run(suite)


if __name__ == '__main__':
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
main()
30 changes: 30 additions & 0 deletions src/pyscripts/simplejson/tests/test_check_circular.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from unittest import TestCase
import simplejson as json

def default_iterable(obj):
return list(obj)

class TestCheckCircular(TestCase):
def test_circular_dict(self):
dct = {}
dct['a'] = dct
self.assertRaises(ValueError, json.dumps, dct)

def test_circular_list(self):
lst = []
lst.append(lst)
self.assertRaises(ValueError, json.dumps, lst)

def test_circular_composite(self):
dct2 = {}
dct2['a'] = []
dct2['a'].append(dct2)
self.assertRaises(ValueError, json.dumps, dct2)

def test_circular_default(self):
json.dumps([set()], default=default_iterable)
self.assertRaises(TypeError, json.dumps, [set()])

def test_circular_off_default(self):
json.dumps([set()], default=default_iterable, check_circular=False)
self.assertRaises(TypeError, json.dumps, [set()], check_circular=False)
33 changes: 33 additions & 0 deletions src/pyscripts/simplejson/tests/test_decimal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from decimal import Decimal
from unittest import TestCase

import simplejson as json

class TestDecimal(TestCase):
NUMS = "1.0", "10.00", "1.1", "1234567890.1234567890", "500"
def test_decimal_encode(self):
for d in map(Decimal, self.NUMS):
self.assertEquals(json.dumps(d, use_decimal=True), str(d))

def test_decimal_decode(self):
for s in self.NUMS:
self.assertEquals(json.loads(s, parse_float=Decimal), Decimal(s))

def test_decimal_roundtrip(self):
for d in map(Decimal, self.NUMS):
# The type might not be the same (int and Decimal) but they
# should still compare equal.
self.assertEquals(
json.loads(
json.dumps(d, use_decimal=True), parse_float=Decimal),
d)
self.assertEquals(
json.loads(
json.dumps([d], use_decimal=True), parse_float=Decimal),
[d])

def test_decimal_defaults(self):
d = Decimal(1)
# use_decimal=False is the default
self.assertRaises(TypeError, json.dumps, d, use_decimal=False)
self.assertRaises(TypeError, json.dumps, d)

0 comments on commit a8f9efe

Please sign in to comment.