def test_simple_dict(self): encoded = { "burned": False, "dimensions": { "thickness": 0.7, "width": 4.5 }, "name": "the best", "toast": True, "toppings": ["jelly", "jam", "butter"] } self.assertDictEqual(encoded, loads(b'\xe5\x06burned\x00\x0adimensions\xe2\x09thickness\x61\xd7\x05width\x62\x4d\x5d\x04name\x88the best\x05toast\x01\x08toppings\xc3\x85jelly\x83jam\x86butter')) self.assertDictEqual(encoded, loads(bytearray(b'\xe5\x06burned\x00\x0adimensions\xe2\x09thickness\x61\xd7\x05width\x62\x4d\x5d\x04name\x88the best\x05toast\x01\x08toppings\xc3\x85jelly\x83jam\x86butter'))) self.assertDictEqual(encoded, loads(memoryview(b'\xe5\x06burned\x00\x0adimensions\xe2\x09thickness\x61\xd7\x05width\x62\x4d\x5d\x04name\x88the best\x05toast\x01\x08toppings\xc3\x85jelly\x83jam\x86butter')))
def assertRoundTrip(self, obj, other, use_for_json=True): if use_for_json is None: # None will use the default s = pbjson.dumps(obj) else: s = pbjson.dumps(obj, use_for_json=use_for_json) self.assertEqual(pbjson.loads(s), other)
def test_floats(self): assert_type = self.assertEqual if pbjson._has_encoder_speedups() else self.assertGreaterEqual for num in [ Decimal("1617161771.7650001"), math.pi, math.pi ** 100, math.pi ** -100, 3.1, 3.1000000001, 3.1000000002, 3.10000000001, 3.100000000001, 3.1000000000001, 3.10000000000001, 0.00012345678901234572, 0.00012345678901234574, 0.00012345678901234576, 0.00012345678901234578, 152.79823, 152.798229999999975, 0.7, ]: encoded = pbjson.dumps(float(num)) decoded = pbjson.loads(encoded) s = str(num) if s[0] == "0": s = s[1:] length = 1 + int((len(s) + 1) / 2) self.assertEqual(decoded, float(num)) assert_type(length, len(encoded), num)
def test_speed(self): if pbjson._has_decoder_speedups(): encoded = json.dumps(sample) start = time() for i in range(100): json.loads(encoded) json_time = time() - start encoded = pbjson.dumps(sample) start = time() for i in range(100): pbjson.loads(encoded) binary_json_time = time() - start # noinspection PyUnboundLocalVariable # print('\nPBJSON: {} seconds\nJSON: {} seconds ({}%)\nMarshal: {} seconds ({}%)\nPickle: {} seconds ({}%)'.format(binary_json_time, json_time, int(json_time / binary_json_time * 100), marshal_time, int(marshal_time / binary_json_time * 100), pickle_time, int(pickle_time / binary_json_time * 100))) self.assertLess(binary_json_time, json_time)
def assertRoundTrip(self, obj, other, use_for_json=True): if use_for_json is None: # None will use the default s = pbjson.dumps(obj) else: s = pbjson.dumps(obj, use_for_json=use_for_json) self.assertEqual( pbjson.loads(s), other)
def test_repeating_keys(self): encoded = { "countries": [ {"code": "us", "name": "United States"}, {"code": "ca", "name": "Canada"}, {"code": "mx", "name": "Mexico"} ], "region": 3, } self.assertEqual(encoded, loads(b'\xe2\x09countries\xc3\xe2\x04code\x82us\x04name\x8DUnited States\xe2\x81\x82ca\x82\x86Canada\xe2\x81\x82mx\x82\x86Mexico\x06region\x21\x03'))
def test_dict_with_long_strings(self): encoded = { "burned": False, "dimensions": { "thickness": 0.7, "width": 4.5 }, "name": "a" * 0x5000, "toast": True, "toppings": ["j" * 0x600, "k" * 0x672, "l" * 0x600] } self.assertEqual(encoded, loads(b'\xe5\x06burned\x00\x0adimensions\xe2\x09thickness\x61\xd7\x05width\x62\x4d\x5d\x04name\x98\x50\x00' + b'a' * 0x5000 + b'\x05toast\x01\x08toppings\xc3\x96\x00' + b'j' * 0x600 + b'\x96\x72' + b'k' * 0x672 + b'\x96\x00' + b'l' * 0x600))
def test_floats(self): assert_type = self.assertEqual if pbjson._has_encoder_speedups() else self.assertGreaterEqual for num in [Decimal('1617161771.7650001'), math.pi, math.pi ** 100, math.pi ** -100, 3.1, 3.1000000001, 3.1000000002, 3.10000000001, 3.100000000001, 3.1000000000001, 3.10000000000001, 0.00012345678901234572, 0.00012345678901234574, 0.00012345678901234576, 0.00012345678901234578, 152.79823, 152.798229999999975, 0.7]: encoded = pbjson.dumps(float(num)) decoded = pbjson.loads(encoded) s = str(num) if s[0] == '0': s = s[1:] length = 1 + int((len(s) + 1) / 2) self.assertEqual(decoded, float(num)) assert_type(length, len(encoded), num)
def main(): parser = argparse.ArgumentParser( description='Convert between pbjson and json', epilog='If converting a PBJSON file with binary elements, you may need to use `--repr` since JSON cannot handle binary data.') parser.add_argument('-r', '--repr', action='store_true', help='instead of converting to JSON, just output the `repr` of the object') parser.add_argument('-p', '--pretty', action='store_true', help='make it nice for humans') if yaml is not None: parser.add_argument('-y', '--yaml', action='store_true', help='input or output is YAML instead of JSON') parser.add_argument('infile', nargs='?', type=argparse.FileType('rb'), default=sys.stdin, help='filename to convert from or to pbjson (default: stdin)') parser.add_argument('outfile', nargs='?', type=argparse.FileType('wb'), default=sys.stdout, help='filename to write the converted file to (default: stdout)') args = parser.parse_args() contents = args.infile.read() try: text = contents.decode() except Exception: text = None if text: if yaml is not None and args.yaml: try: obj = yaml.load(text, Loader=Loader) except ValueError: raise SystemExit(sys.exc_info()[1]) else: try: obj = json.loads(text, object_pairs_hook=OrderedDict) except ValueError: if yaml is None: raise SystemExit(sys.exc_info()[1]) try: obj = yaml.load(text, Loader=Loader) except ValueError: raise SystemExit(sys.exc_info()[1]) pbjson.dump(obj, args.outfile) else: try: obj = pbjson.loads(contents, document_class=OrderedDict) except ValueError: raise SystemExit(sys.exc_info()[1]) if yaml is not None and args.yaml: j = yaml.dump(obj, Dumper=Dumper) elif args.repr: j = pprint.pformat(obj, indent=1) if args.pretty else repr(obj) else: kw = {'ensure_ascii': False} if does_unicode else {} j = json.dumps(obj, sort_keys=True, indent=4 if args.pretty else None, **kw) if args.outfile == sys.stdout: j += '\n' else: j = j.encode() args.outfile.write(j)
def test_european(self): original = ['Politique de Confidentialité', 'Política de Privacidad'] pbj = pbjson.dumps(original) round_trip = pbjson.loads(pbj) self.assertEqual(original, round_trip) with open('temp.pbj', 'wb') as f: f.write(pbj) with open('temp.pbj', 'rb') as f: fpbj = f.read() self.assertEqual(pbj, fpbj) with open('temp.pbj', 'rb') as f: round_trip = pbjson.load(f) self.assertEqual(original, round_trip)
def test_asian(self): original = ['その子は絶えずくすくす笑っていた', 'お役に立てば幸いです。'] pbj = pbjson.dumps(original) round_trip = pbjson.loads(pbj) self.assertEqual(original, round_trip) with open('temp.pbj', 'wb') as f: f.write(pbj) with open('temp.pbj', 'rb') as f: fpbj = f.read() self.assertEqual(pbj, fpbj) with open('temp.pbj', 'rb') as f: round_trip = pbjson.load(f) self.assertEqual(original, round_trip)
def test_ordered_dict(self): encoded = OrderedDict(( ("burned", False), ("dimensions", OrderedDict(( ("thickness", 0.7), ("width", 4.5)))), ("name", "the best"), ("toast", True), ("toppings", ["jelly", "jam", "butter"]) )) decoded = loads(b'\xe5\x06burned\x00\x0adimensions\xe2\x09thickness\x61\xd7\x05width\x62\x4d\x5d\x04name\x88the best\x05toast\x01\x08toppings\xc3\x85jelly\x83jam\x86butter', document_class=OrderedDict) self.assertEqual(encoded, decoded) self.assertIsInstance(decoded, OrderedDict) self.assertIsInstance(decoded['dimensions'], OrderedDict)
def test_decode_medium_length_string(self): self.assertEqual('Now is the time for all good men', loads(b'\x90\x20Now is the time for all good men'))
def test_decode_none(self): self.assertIs(None, loads(b'\x02'))
def test_decode_string(self): self.assertEqual('test', loads(b'\x84test'))
def test_decode_false(self): self.assertIs(False, loads(b'\x00'))
def test_decode_true(self): self.assertIs(True, loads(b'\x01'))
def test_three_byte_int(self): self.assertEqual(0x40000, loads(b'\x23\x04\x00\x00')) self.assertEqual(-0x40000, loads(b'\x43\x04\x00\x00'))
def test_simple_list(self): self.assertEqual(['jelly', 'jam', 'butter'], loads(b'\xc3\x85jelly\x83jam\x86butter'))
def test_degenerates_allow(self): for inf in (float('inf'), float('-inf')): self.assertEqual(pbjson.loads(pbjson.dumps(inf)), inf) # Python 2.5 doesn't have math.isnan nan = pbjson.loads(pbjson.dumps(float('nan'))) self.assertTrue((0 + nan) != nan)
def test_two_byte_int(self): self.assertEqual(0x400, loads(b'\x22\x04\x00')) self.assertEqual(-0x400, loads(b'\x42\x04\x00'))
def test_nan(self): value = loads(b'\x05') self.assertNotEqual(value, value)
def test_short_decimal(self): self.assertEqual(Decimal('4.5'), loads(b'\x62\x4d\x5d', float_class=Decimal)) self.assertEqual(Decimal('-4.5'), loads(b'\x62\xb4\xd5', float_class=Decimal))
def test_long_decimal(self): self.assertEqual(Decimal('152.79823123456789012345678901200'), loads(b'\x70\x11\x15\x2d\x79\x82\x31\x23\x45\x67\x89\x01\x23\x45\x67\x89\x01\x20\x0d', float_class=Decimal)) self.assertEqual(Decimal('-152.79823123456789012345678901200'), loads(b'\x70\x11\xb1\x52\xd7\x98\x23\x12\x34\x56\x78\x90\x12\x34\x56\x78\x90\x12\x00', float_class=Decimal))
def test_infinity(self): self.assertEqual(float('inf'), loads(b'\x03'))
def test_generator_list(self): self.assertEqual([0, 1, 2], loads(b'\x0c\x20\x21\x01\x21\x02\x0f'))
def test_decode_long_string(self): encoded = pack('!BH', 0x98, 2100) + b'a' * 2100 decoded = loads(encoded) self.assertEqual('a' * 2100, decoded)
def test_five_byte_int(self): self.assertEqual(0x400000000, loads(b'\x25\x04\x00\x00\x00\x00')) self.assertEqual(-0x400000000, loads(b'\x45\x04\x00\x00\x00\x00'))
def test_decode_unicode(self): self.assertEqual('test', loads(b'\x84test'))
def test_four_byte_int(self): self.assertEqual(0x4000000, loads(b'\x24\x04\x00\x00\x00')) self.assertEqual(-0x4000000, loads(b'\x44\x04\x00\x00\x00'))
def test_ints(self): for num in [1, long_type(1), 1 << 32, 1 << 64]: self.assertEqual(pbjson.loads(pbjson.dumps(num)), num)
def test_sixteen_byte_int(self): self.assertEqual(0x4000000000000000000000000000000, loads(b'\x30\x10\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')) self.assertEqual(-0x4000000000000000000000000000000, loads(b'\x50\x10\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'))
def test_negative_infinity(self): self.assertEqual(float('-inf'), loads(b'\x04'))
def test_one_byte_int(self): self.assertEqual(4, loads(b'\x21\x04')) self.assertEqual(-4, loads(b'\x41\x04'))