/usr/lib/python2.7/dist-packages/ijson/common.py is in python-ijson 2.3-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | '''
Backend independent higher level interfaces, common exceptions.
'''
import decimal
class JSONError(Exception):
'''
Base exception for all parsing errors.
'''
pass
class IncompleteJSONError(JSONError):
'''
Raised when the parser can't read expected data from a stream.
'''
pass
def parse(basic_events):
'''
An iterator returning parsing events with the information about their location
with the JSON object tree. Events are tuples ``(prefix, type, value)``.
Available types and values are:
('null', None)
('boolean', <True or False>)
('number', <int or Decimal>)
('string', <unicode>)
('map_key', <str>)
('start_map', None)
('end_map', None)
('start_array', None)
('end_array', None)
Prefixes represent the path to the nested elements from the root of the JSON
document. For example, given this document::
{
"array": [1, 2],
"map": {
"key": "value"
}
}
the parser would yield events:
('', 'start_map', None)
('', 'map_key', 'array')
('array', 'start_array', None)
('array.item', 'number', 1)
('array.item', 'number', 2)
('array', 'end_array', None)
('', 'map_key', 'map')
('map', 'start_map', None)
('map', 'map_key', 'key')
('map.key', 'string', u'value')
('map', 'end_map', None)
('', 'end_map', None)
'''
path = []
for event, value in basic_events:
if event == 'map_key':
prefix = '.'.join(path[:-1])
path[-1] = value
elif event == 'start_map':
prefix = '.'.join(path)
path.append(None)
elif event == 'end_map':
path.pop()
prefix = '.'.join(path)
elif event == 'start_array':
prefix = '.'.join(path)
path.append('item')
elif event == 'end_array':
path.pop()
prefix = '.'.join(path)
else: # any scalar value
prefix = '.'.join(path)
yield prefix, event, value
class ObjectBuilder(object):
'''
Incrementally builds an object from JSON parser events. Events are passed
into the `event` function that accepts two parameters: event type and
value. The object being built is available at any time from the `value`
attribute.
Example::
from StringIO import StringIO
from ijson.parse import basic_parse
from ijson.utils import ObjectBuilder
builder = ObjectBuilder()
f = StringIO('{"key": "value"})
for event, value in basic_parse(f):
builder.event(event, value)
print builder.value
'''
def __init__(self):
def initial_set(value):
self.value = value
self.containers = [initial_set]
def event(self, event, value):
if event == 'map_key':
self.key = value
elif event == 'start_map':
map = {}
self.containers[-1](map)
def setter(value):
map[self.key] = value
self.containers.append(setter)
elif event == 'start_array':
array = []
self.containers[-1](array)
self.containers.append(array.append)
elif event == 'end_array' or event == 'end_map':
self.containers.pop()
else:
self.containers[-1](value)
def items(prefixed_events, prefix):
'''
An iterator returning native Python objects constructed from the events
under a given prefix.
'''
prefixed_events = iter(prefixed_events)
try:
while True:
current, event, value = next(prefixed_events)
if current == prefix:
if event in ('start_map', 'start_array'):
builder = ObjectBuilder()
end_event = event.replace('start', 'end')
while (current, event) != (prefix, end_event):
builder.event(event, value)
current, event, value = next(prefixed_events)
yield builder.value
else:
yield value
except StopIteration:
pass
def number(str_value):
'''
Converts string with a numeric value into an int or a Decimal.
Used in different backends for consistent number representation.
'''
number = decimal.Decimal(str_value)
int_number = int(number)
if int_number == number:
number = int_number
return number
|