import json
from json.encoder import * # Don't do this though
def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
_key_separator, _item_separator, _sort_keys, _skipkeys, _one_shot,
## HACK: hand-optimized bytecode; turn globals into locals
ValueError=ValueError,
basestring=basestring,
dict=dict,
float=float,
id=id,
int=int,
isinstance=isinstance,
list=list,
long=long,
str=str,
tuple=tuple,
):
if _indent is not None and not isinstance(_indent, str):
_indent = ' ' * _indent
def _iterencode_list(lst, _current_indent_level):
if not lst:
yield '[]'
return
if markers is not None:
markerid = id(lst)
if markerid in markers:
raise ValueError("Circular reference detected")
markers[markerid] = lst
buf = '['
if _indent is not None:
_current_indent_level += 1
newline_indent = '\n' + _indent * _current_indent_level
separator = _item_separator + newline_indent
buf += newline_indent
else:
newline_indent = None
separator = _item_separator
first = True
for value in lst:
if first:
first = False
else:
buf = separator
if isinstance(value, basestring):
yield buf + _encoder(value)
elif value is None:
yield buf + 'null'
elif value is True:
yield buf + 'true'
elif value is False:
yield buf + 'false'
elif isinstance(value, (int, long)):
yield buf + str(value)
elif isinstance(value, float):
yield buf + _floatstr(value)
else:
yield buf
if isinstance(value, (list, tuple)):
chunks = _iterencode_list(value, _current_indent_level)
elif isinstance(value, dict):
chunks = _iterencode_dict(value, _current_indent_level)
else:
chunks = _iterencode(value, _current_indent_level)
for chunk in chunks:
yield chunk
if newline_indent is not None:
_current_indent_level -= 1
yield '\n' + _indent * _current_indent_level
yield ']'
if markers is not None:
del markers[markerid]
def _iterencode_dict(dct, _current_indent_level):
if not dct:
yield '{}'
return
if markers is not None:
markerid = id(dct)
if markerid in markers:
raise ValueError("Circular reference detected")
markers[markerid] = dct
yield '{'
if _indent is not None:
_current_indent_level += 1
newline_indent = '\n' + _indent * _current_indent_level
item_separator = _item_separator + newline_indent
yield newline_indent
else:
newline_indent = None
item_separator = _item_separator
first = True
if _sort_keys:
items = sorted(dct.items(), key=lambda kv: kv[0])
else:
items = dct.iteritems()
for key, value in items:
if isinstance(key, basestring):
pass
# JavaScript is weakly typed for these, so it makes sense to
# also allow them. Many encoders seem to do something like this.
elif isinstance(key, float):
key = _floatstr(key)
elif key is True:
key = 'true'
elif key is False:
key = 'false'
elif key is None:
key = 'null'
elif isinstance(key, (int, long)):
key = str(key)
elif _skipkeys:
continue
else:
raise TypeError("key " + repr(key) + " is not a string")
if first:
first = False
else:
yield item_separator
yield _encoder(key)
yield _key_separator
if isinstance(value, basestring):
yield _encoder(value)
elif value is None:
yield 'null'
elif value is True:
yield 'true'
elif value is False:
yield 'false'
elif isinstance(value, (int, long)):
yield str(value)
elif isinstance(value, float):
yield _floatstr(value)
else:
if isinstance(value, (list, tuple)):
chunks = _iterencode_list(value, _current_indent_level)
elif isinstance(value, dict):
chunks = _iterencode_dict(value, _current_indent_level)
else:
chunks = _iterencode(value, _current_indent_level)
for chunk in chunks:
yield chunk
if newline_indent is not None:
_current_indent_level -= 1
yield '\n' + _indent * _current_indent_level
yield '}'
if markers is not None:
del markers[markerid]
def _iterencode(o, _current_indent_level):
if isinstance(o, basestring):
yield _encoder(o)
elif o is None:
yield 'null'
elif o is True:
yield 'true'
elif o is False:
yield 'false'
elif isinstance(o, (int, long)):
yield str(o)
elif isinstance(o, float):
yield _floatstr(o)
elif isinstance(o, (list, tuple)):
for chunk in _iterencode_list(o, _current_indent_level):
yield chunk
elif isinstance(o, dict):
for chunk in _iterencode_dict(o, _current_indent_level):
yield chunk
else:
if markers is not None:
markerid = id(o)
if markerid in markers:
raise ValueError("Circular reference detected")
markers[markerid] = o
o = _default(o)
for chunk in _iterencode(o, _current_indent_level):
yield chunk
if markers is not None:
del markers[markerid]
return _iterencode
class CustomJSONEncoder(JSONEncoder):
def iterencode(self, o, _one_shot=False):
"""Encode the given object and yield each string
representation as available.
For example::
for chunk in JSONEncoder().iterencode(bigobject):
mysocket.write(chunk)
"""
if self.check_circular:
markers = {}
else:
markers = None
if self.ensure_ascii:
_encoder = encode_basestring_ascii
else:
_encoder = encode_basestring
if self.encoding != 'utf-8':
def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding):
if isinstance(o, str):
o = o.decode(_encoding)
return _orig_encoder(o)
def floatstr(o, allow_nan=self.allow_nan,
_repr=FLOAT_REPR, _inf=INFINITY, _neginf=-INFINITY):
# Check for specials. Note that this type of test is processor
# and/or platform-specific, so do tests which don't depend on the
# internals.
if o != o:
text = 'NaN'
elif o == _inf:
text = 'Infinity'
elif o == _neginf:
text = '-Infinity'
else:
return _repr(o)
if not allow_nan:
raise ValueError(
"Out of range float values are not JSON compliant: " +
repr(o))
return text
if (_one_shot and c_make_encoder is not None
and self.indent is None and not self.sort_keys):
_iterencode = c_make_encoder(
markers, self.default, _encoder, self.indent,
self.key_separator, self.item_separator, self.sort_keys,
self.skipkeys, self.allow_nan)
else:
_iterencode = _make_iterencode(
markers, self.default, _encoder, self.indent, floatstr,
self.key_separator, self.item_separator, self.sort_keys,
self.skipkeys, _one_shot)
return _iterencode(o, 0)
data = {'a': {'b': {'c': 1}}}
print repr(json.dumps(data, cls=CustomJSONEncoder, indent='\t'))
aW1wb3J0IGpzb24KZnJvbSBqc29uLmVuY29kZXIgaW1wb3J0ICogICMgRG9uJ3QgZG8gdGhpcyB0aG91Z2gKCgpkZWYgX21ha2VfaXRlcmVuY29kZShtYXJrZXJzLCBfZGVmYXVsdCwgX2VuY29kZXIsIF9pbmRlbnQsIF9mbG9hdHN0ciwKICAgICAgICBfa2V5X3NlcGFyYXRvciwgX2l0ZW1fc2VwYXJhdG9yLCBfc29ydF9rZXlzLCBfc2tpcGtleXMsIF9vbmVfc2hvdCwKICAgICAgICAjIyBIQUNLOiBoYW5kLW9wdGltaXplZCBieXRlY29kZTsgdHVybiBnbG9iYWxzIGludG8gbG9jYWxzCiAgICAgICAgVmFsdWVFcnJvcj1WYWx1ZUVycm9yLAogICAgICAgIGJhc2VzdHJpbmc9YmFzZXN0cmluZywKICAgICAgICBkaWN0PWRpY3QsCiAgICAgICAgZmxvYXQ9ZmxvYXQsCiAgICAgICAgaWQ9aWQsCiAgICAgICAgaW50PWludCwKICAgICAgICBpc2luc3RhbmNlPWlzaW5zdGFuY2UsCiAgICAgICAgbGlzdD1saXN0LAogICAgICAgIGxvbmc9bG9uZywKICAgICAgICBzdHI9c3RyLAogICAgICAgIHR1cGxlPXR1cGxlLAogICAgKToKCiAgICBpZiBfaW5kZW50IGlzIG5vdCBOb25lIGFuZCBub3QgaXNpbnN0YW5jZShfaW5kZW50LCBzdHIpOgogICAgICAgIF9pbmRlbnQgPSAnICcgKiBfaW5kZW50CgogICAgZGVmIF9pdGVyZW5jb2RlX2xpc3QobHN0LCBfY3VycmVudF9pbmRlbnRfbGV2ZWwpOgogICAgICAgIGlmIG5vdCBsc3Q6CiAgICAgICAgICAgIHlpZWxkICdbXScKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgaWYgbWFya2VycyBpcyBub3QgTm9uZToKICAgICAgICAgICAgbWFya2VyaWQgPSBpZChsc3QpCiAgICAgICAgICAgIGlmIG1hcmtlcmlkIGluIG1hcmtlcnM6CiAgICAgICAgICAgICAgICByYWlzZSBWYWx1ZUVycm9yKCJDaXJjdWxhciByZWZlcmVuY2UgZGV0ZWN0ZWQiKQogICAgICAgICAgICBtYXJrZXJzW21hcmtlcmlkXSA9IGxzdAogICAgICAgIGJ1ZiA9ICdbJwogICAgICAgIGlmIF9pbmRlbnQgaXMgbm90IE5vbmU6CiAgICAgICAgICAgIF9jdXJyZW50X2luZGVudF9sZXZlbCArPSAxCiAgICAgICAgICAgIG5ld2xpbmVfaW5kZW50ID0gJ1xuJyArIF9pbmRlbnQgKiBfY3VycmVudF9pbmRlbnRfbGV2ZWwKICAgICAgICAgICAgc2VwYXJhdG9yID0gX2l0ZW1fc2VwYXJhdG9yICsgbmV3bGluZV9pbmRlbnQKICAgICAgICAgICAgYnVmICs9IG5ld2xpbmVfaW5kZW50CiAgICAgICAgZWxzZToKICAgICAgICAgICAgbmV3bGluZV9pbmRlbnQgPSBOb25lCiAgICAgICAgICAgIHNlcGFyYXRvciA9IF9pdGVtX3NlcGFyYXRvcgogICAgICAgIGZpcnN0ID0gVHJ1ZQogICAgICAgIGZvciB2YWx1ZSBpbiBsc3Q6CiAgICAgICAgICAgIGlmIGZpcnN0OgogICAgICAgICAgICAgICAgZmlyc3QgPSBGYWxzZQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgYnVmID0gc2VwYXJhdG9yCiAgICAgICAgICAgIGlmIGlzaW5zdGFuY2UodmFsdWUsIGJhc2VzdHJpbmcpOgogICAgICAgICAgICAgICAgeWllbGQgYnVmICsgX2VuY29kZXIodmFsdWUpCiAgICAgICAgICAgIGVsaWYgdmFsdWUgaXMgTm9uZToKICAgICAgICAgICAgICAgIHlpZWxkIGJ1ZiArICdudWxsJwogICAgICAgICAgICBlbGlmIHZhbHVlIGlzIFRydWU6CiAgICAgICAgICAgICAgICB5aWVsZCBidWYgKyAndHJ1ZScKICAgICAgICAgICAgZWxpZiB2YWx1ZSBpcyBGYWxzZToKICAgICAgICAgICAgICAgIHlpZWxkIGJ1ZiArICdmYWxzZScKICAgICAgICAgICAgZWxpZiBpc2luc3RhbmNlKHZhbHVlLCAoaW50LCBsb25nKSk6CiAgICAgICAgICAgICAgICB5aWVsZCBidWYgKyBzdHIodmFsdWUpCiAgICAgICAgICAgIGVsaWYgaXNpbnN0YW5jZSh2YWx1ZSwgZmxvYXQpOgogICAgICAgICAgICAgICAgeWllbGQgYnVmICsgX2Zsb2F0c3RyKHZhbHVlKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgeWllbGQgYnVmCiAgICAgICAgICAgICAgICBpZiBpc2luc3RhbmNlKHZhbHVlLCAobGlzdCwgdHVwbGUpKToKICAgICAgICAgICAgICAgICAgICBjaHVua3MgPSBfaXRlcmVuY29kZV9saXN0KHZhbHVlLCBfY3VycmVudF9pbmRlbnRfbGV2ZWwpCiAgICAgICAgICAgICAgICBlbGlmIGlzaW5zdGFuY2UodmFsdWUsIGRpY3QpOgogICAgICAgICAgICAgICAgICAgIGNodW5rcyA9IF9pdGVyZW5jb2RlX2RpY3QodmFsdWUsIF9jdXJyZW50X2luZGVudF9sZXZlbCkKICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgY2h1bmtzID0gX2l0ZXJlbmNvZGUodmFsdWUsIF9jdXJyZW50X2luZGVudF9sZXZlbCkKICAgICAgICAgICAgICAgIGZvciBjaHVuayBpbiBjaHVua3M6CiAgICAgICAgICAgICAgICAgICAgeWllbGQgY2h1bmsKICAgICAgICBpZiBuZXdsaW5lX2luZGVudCBpcyBub3QgTm9uZToKICAgICAgICAgICAgX2N1cnJlbnRfaW5kZW50X2xldmVsIC09IDEKICAgICAgICAgICAgeWllbGQgJ1xuJyArIF9pbmRlbnQgKiBfY3VycmVudF9pbmRlbnRfbGV2ZWwKICAgICAgICB5aWVsZCAnXScKICAgICAgICBpZiBtYXJrZXJzIGlzIG5vdCBOb25lOgogICAgICAgICAgICBkZWwgbWFya2Vyc1ttYXJrZXJpZF0KCiAgICBkZWYgX2l0ZXJlbmNvZGVfZGljdChkY3QsIF9jdXJyZW50X2luZGVudF9sZXZlbCk6CiAgICAgICAgaWYgbm90IGRjdDoKICAgICAgICAgICAgeWllbGQgJ3t9JwogICAgICAgICAgICByZXR1cm4KICAgICAgICBpZiBtYXJrZXJzIGlzIG5vdCBOb25lOgogICAgICAgICAgICBtYXJrZXJpZCA9IGlkKGRjdCkKICAgICAgICAgICAgaWYgbWFya2VyaWQgaW4gbWFya2VyczoKICAgICAgICAgICAgICAgIHJhaXNlIFZhbHVlRXJyb3IoIkNpcmN1bGFyIHJlZmVyZW5jZSBkZXRlY3RlZCIpCiAgICAgICAgICAgIG1hcmtlcnNbbWFya2VyaWRdID0gZGN0CiAgICAgICAgeWllbGQgJ3snCiAgICAgICAgaWYgX2luZGVudCBpcyBub3QgTm9uZToKICAgICAgICAgICAgX2N1cnJlbnRfaW5kZW50X2xldmVsICs9IDEKICAgICAgICAgICAgbmV3bGluZV9pbmRlbnQgPSAnXG4nICsgX2luZGVudCAqIF9jdXJyZW50X2luZGVudF9sZXZlbAogICAgICAgICAgICBpdGVtX3NlcGFyYXRvciA9IF9pdGVtX3NlcGFyYXRvciArIG5ld2xpbmVfaW5kZW50CiAgICAgICAgICAgIHlpZWxkIG5ld2xpbmVfaW5kZW50CiAgICAgICAgZWxzZToKICAgICAgICAgICAgbmV3bGluZV9pbmRlbnQgPSBOb25lCiAgICAgICAgICAgIGl0ZW1fc2VwYXJhdG9yID0gX2l0ZW1fc2VwYXJhdG9yCiAgICAgICAgZmlyc3QgPSBUcnVlCiAgICAgICAgaWYgX3NvcnRfa2V5czoKICAgICAgICAgICAgaXRlbXMgPSBzb3J0ZWQoZGN0Lml0ZW1zKCksIGtleT1sYW1iZGEga3Y6IGt2WzBdKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIGl0ZW1zID0gZGN0Lml0ZXJpdGVtcygpCiAgICAgICAgZm9yIGtleSwgdmFsdWUgaW4gaXRlbXM6CiAgICAgICAgICAgIGlmIGlzaW5zdGFuY2Uoa2V5LCBiYXNlc3RyaW5nKToKICAgICAgICAgICAgICAgIHBhc3MKICAgICAgICAgICAgIyBKYXZhU2NyaXB0IGlzIHdlYWtseSB0eXBlZCBmb3IgdGhlc2UsIHNvIGl0IG1ha2VzIHNlbnNlIHRvCiAgICAgICAgICAgICMgYWxzbyBhbGxvdyB0aGVtLiAgTWFueSBlbmNvZGVycyBzZWVtIHRvIGRvIHNvbWV0aGluZyBsaWtlIHRoaXMuCiAgICAgICAgICAgIGVsaWYgaXNpbnN0YW5jZShrZXksIGZsb2F0KToKICAgICAgICAgICAgICAgIGtleSA9IF9mbG9hdHN0cihrZXkpCiAgICAgICAgICAgIGVsaWYga2V5IGlzIFRydWU6CiAgICAgICAgICAgICAgICBrZXkgPSAndHJ1ZScKICAgICAgICAgICAgZWxpZiBrZXkgaXMgRmFsc2U6CiAgICAgICAgICAgICAgICBrZXkgPSAnZmFsc2UnCiAgICAgICAgICAgIGVsaWYga2V5IGlzIE5vbmU6CiAgICAgICAgICAgICAgICBrZXkgPSAnbnVsbCcKICAgICAgICAgICAgZWxpZiBpc2luc3RhbmNlKGtleSwgKGludCwgbG9uZykpOgogICAgICAgICAgICAgICAga2V5ID0gc3RyKGtleSkKICAgICAgICAgICAgZWxpZiBfc2tpcGtleXM6CiAgICAgICAgICAgICAgICBjb250aW51ZQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgcmFpc2UgVHlwZUVycm9yKCJrZXkgIiArIHJlcHIoa2V5KSArICIgaXMgbm90IGEgc3RyaW5nIikKICAgICAgICAgICAgaWYgZmlyc3Q6CiAgICAgICAgICAgICAgICBmaXJzdCA9IEZhbHNlCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICB5aWVsZCBpdGVtX3NlcGFyYXRvcgogICAgICAgICAgICB5aWVsZCBfZW5jb2RlcihrZXkpCiAgICAgICAgICAgIHlpZWxkIF9rZXlfc2VwYXJhdG9yCiAgICAgICAgICAgIGlmIGlzaW5zdGFuY2UodmFsdWUsIGJhc2VzdHJpbmcpOgogICAgICAgICAgICAgICAgeWllbGQgX2VuY29kZXIodmFsdWUpCiAgICAgICAgICAgIGVsaWYgdmFsdWUgaXMgTm9uZToKICAgICAgICAgICAgICAgIHlpZWxkICdudWxsJwogICAgICAgICAgICBlbGlmIHZhbHVlIGlzIFRydWU6CiAgICAgICAgICAgICAgICB5aWVsZCAndHJ1ZScKICAgICAgICAgICAgZWxpZiB2YWx1ZSBpcyBGYWxzZToKICAgICAgICAgICAgICAgIHlpZWxkICdmYWxzZScKICAgICAgICAgICAgZWxpZiBpc2luc3RhbmNlKHZhbHVlLCAoaW50LCBsb25nKSk6CiAgICAgICAgICAgICAgICB5aWVsZCBzdHIodmFsdWUpCiAgICAgICAgICAgIGVsaWYgaXNpbnN0YW5jZSh2YWx1ZSwgZmxvYXQpOgogICAgICAgICAgICAgICAgeWllbGQgX2Zsb2F0c3RyKHZhbHVlKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgaWYgaXNpbnN0YW5jZSh2YWx1ZSwgKGxpc3QsIHR1cGxlKSk6CiAgICAgICAgICAgICAgICAgICAgY2h1bmtzID0gX2l0ZXJlbmNvZGVfbGlzdCh2YWx1ZSwgX2N1cnJlbnRfaW5kZW50X2xldmVsKQogICAgICAgICAgICAgICAgZWxpZiBpc2luc3RhbmNlKHZhbHVlLCBkaWN0KToKICAgICAgICAgICAgICAgICAgICBjaHVua3MgPSBfaXRlcmVuY29kZV9kaWN0KHZhbHVlLCBfY3VycmVudF9pbmRlbnRfbGV2ZWwpCiAgICAgICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgICAgIGNodW5rcyA9IF9pdGVyZW5jb2RlKHZhbHVlLCBfY3VycmVudF9pbmRlbnRfbGV2ZWwpCiAgICAgICAgICAgICAgICBmb3IgY2h1bmsgaW4gY2h1bmtzOgogICAgICAgICAgICAgICAgICAgIHlpZWxkIGNodW5rCiAgICAgICAgaWYgbmV3bGluZV9pbmRlbnQgaXMgbm90IE5vbmU6CiAgICAgICAgICAgIF9jdXJyZW50X2luZGVudF9sZXZlbCAtPSAxCiAgICAgICAgICAgIHlpZWxkICdcbicgKyBfaW5kZW50ICogX2N1cnJlbnRfaW5kZW50X2xldmVsCiAgICAgICAgeWllbGQgJ30nCiAgICAgICAgaWYgbWFya2VycyBpcyBub3QgTm9uZToKICAgICAgICAgICAgZGVsIG1hcmtlcnNbbWFya2VyaWRdCgogICAgZGVmIF9pdGVyZW5jb2RlKG8sIF9jdXJyZW50X2luZGVudF9sZXZlbCk6CiAgICAgICAgaWYgaXNpbnN0YW5jZShvLCBiYXNlc3RyaW5nKToKICAgICAgICAgICAgeWllbGQgX2VuY29kZXIobykKICAgICAgICBlbGlmIG8gaXMgTm9uZToKICAgICAgICAgICAgeWllbGQgJ251bGwnCiAgICAgICAgZWxpZiBvIGlzIFRydWU6CiAgICAgICAgICAgIHlpZWxkICd0cnVlJwogICAgICAgIGVsaWYgbyBpcyBGYWxzZToKICAgICAgICAgICAgeWllbGQgJ2ZhbHNlJwogICAgICAgIGVsaWYgaXNpbnN0YW5jZShvLCAoaW50LCBsb25nKSk6CiAgICAgICAgICAgIHlpZWxkIHN0cihvKQogICAgICAgIGVsaWYgaXNpbnN0YW5jZShvLCBmbG9hdCk6CiAgICAgICAgICAgIHlpZWxkIF9mbG9hdHN0cihvKQogICAgICAgIGVsaWYgaXNpbnN0YW5jZShvLCAobGlzdCwgdHVwbGUpKToKICAgICAgICAgICAgZm9yIGNodW5rIGluIF9pdGVyZW5jb2RlX2xpc3QobywgX2N1cnJlbnRfaW5kZW50X2xldmVsKToKICAgICAgICAgICAgICAgIHlpZWxkIGNodW5rCiAgICAgICAgZWxpZiBpc2luc3RhbmNlKG8sIGRpY3QpOgogICAgICAgICAgICBmb3IgY2h1bmsgaW4gX2l0ZXJlbmNvZGVfZGljdChvLCBfY3VycmVudF9pbmRlbnRfbGV2ZWwpOgogICAgICAgICAgICAgICAgeWllbGQgY2h1bmsKICAgICAgICBlbHNlOgogICAgICAgICAgICBpZiBtYXJrZXJzIGlzIG5vdCBOb25lOgogICAgICAgICAgICAgICAgbWFya2VyaWQgPSBpZChvKQogICAgICAgICAgICAgICAgaWYgbWFya2VyaWQgaW4gbWFya2VyczoKICAgICAgICAgICAgICAgICAgICByYWlzZSBWYWx1ZUVycm9yKCJDaXJjdWxhciByZWZlcmVuY2UgZGV0ZWN0ZWQiKQogICAgICAgICAgICAgICAgbWFya2Vyc1ttYXJrZXJpZF0gPSBvCiAgICAgICAgICAgIG8gPSBfZGVmYXVsdChvKQogICAgICAgICAgICBmb3IgY2h1bmsgaW4gX2l0ZXJlbmNvZGUobywgX2N1cnJlbnRfaW5kZW50X2xldmVsKToKICAgICAgICAgICAgICAgIHlpZWxkIGNodW5rCiAgICAgICAgICAgIGlmIG1hcmtlcnMgaXMgbm90IE5vbmU6CiAgICAgICAgICAgICAgICBkZWwgbWFya2Vyc1ttYXJrZXJpZF0KCiAgICByZXR1cm4gX2l0ZXJlbmNvZGUKCgpjbGFzcyBDdXN0b21KU09ORW5jb2RlcihKU09ORW5jb2Rlcik6CiAgICBkZWYgaXRlcmVuY29kZShzZWxmLCBvLCBfb25lX3Nob3Q9RmFsc2UpOgogICAgICAgICIiIkVuY29kZSB0aGUgZ2l2ZW4gb2JqZWN0IGFuZCB5aWVsZCBlYWNoIHN0cmluZwogICAgICAgIHJlcHJlc2VudGF0aW9uIGFzIGF2YWlsYWJsZS4KCiAgICAgICAgRm9yIGV4YW1wbGU6OgoKICAgICAgICAgICAgZm9yIGNodW5rIGluIEpTT05FbmNvZGVyKCkuaXRlcmVuY29kZShiaWdvYmplY3QpOgogICAgICAgICAgICAgICAgbXlzb2NrZXQud3JpdGUoY2h1bmspCgogICAgICAgICIiIgogICAgICAgIGlmIHNlbGYuY2hlY2tfY2lyY3VsYXI6CiAgICAgICAgICAgIG1hcmtlcnMgPSB7fQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIG1hcmtlcnMgPSBOb25lCiAgICAgICAgaWYgc2VsZi5lbnN1cmVfYXNjaWk6CiAgICAgICAgICAgIF9lbmNvZGVyID0gZW5jb2RlX2Jhc2VzdHJpbmdfYXNjaWkKICAgICAgICBlbHNlOgogICAgICAgICAgICBfZW5jb2RlciA9IGVuY29kZV9iYXNlc3RyaW5nCiAgICAgICAgaWYgc2VsZi5lbmNvZGluZyAhPSAndXRmLTgnOgogICAgICAgICAgICBkZWYgX2VuY29kZXIobywgX29yaWdfZW5jb2Rlcj1fZW5jb2RlciwgX2VuY29kaW5nPXNlbGYuZW5jb2RpbmcpOgogICAgICAgICAgICAgICAgaWYgaXNpbnN0YW5jZShvLCBzdHIpOgogICAgICAgICAgICAgICAgICAgIG8gPSBvLmRlY29kZShfZW5jb2RpbmcpCiAgICAgICAgICAgICAgICByZXR1cm4gX29yaWdfZW5jb2RlcihvKQoKICAgICAgICBkZWYgZmxvYXRzdHIobywgYWxsb3dfbmFuPXNlbGYuYWxsb3dfbmFuLAogICAgICAgICAgICAgICAgX3JlcHI9RkxPQVRfUkVQUiwgX2luZj1JTkZJTklUWSwgX25lZ2luZj0tSU5GSU5JVFkpOgogICAgICAgICAgICAjIENoZWNrIGZvciBzcGVjaWFscy4gIE5vdGUgdGhhdCB0aGlzIHR5cGUgb2YgdGVzdCBpcyBwcm9jZXNzb3IKICAgICAgICAgICAgIyBhbmQvb3IgcGxhdGZvcm0tc3BlY2lmaWMsIHNvIGRvIHRlc3RzIHdoaWNoIGRvbid0IGRlcGVuZCBvbiB0aGUKICAgICAgICAgICAgIyBpbnRlcm5hbHMuCgogICAgICAgICAgICBpZiBvICE9IG86CiAgICAgICAgICAgICAgICB0ZXh0ID0gJ05hTicKICAgICAgICAgICAgZWxpZiBvID09IF9pbmY6CiAgICAgICAgICAgICAgICB0ZXh0ID0gJ0luZmluaXR5JwogICAgICAgICAgICBlbGlmIG8gPT0gX25lZ2luZjoKICAgICAgICAgICAgICAgIHRleHQgPSAnLUluZmluaXR5JwogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgcmV0dXJuIF9yZXByKG8pCgogICAgICAgICAgICBpZiBub3QgYWxsb3dfbmFuOgogICAgICAgICAgICAgICAgcmFpc2UgVmFsdWVFcnJvcigKICAgICAgICAgICAgICAgICAgICAiT3V0IG9mIHJhbmdlIGZsb2F0IHZhbHVlcyBhcmUgbm90IEpTT04gY29tcGxpYW50OiAiICsKICAgICAgICAgICAgICAgICAgICByZXByKG8pKQoKICAgICAgICAgICAgcmV0dXJuIHRleHQKCgogICAgICAgIGlmIChfb25lX3Nob3QgYW5kIGNfbWFrZV9lbmNvZGVyIGlzIG5vdCBOb25lCiAgICAgICAgICAgICAgICBhbmQgc2VsZi5pbmRlbnQgaXMgTm9uZSBhbmQgbm90IHNlbGYuc29ydF9rZXlzKToKICAgICAgICAgICAgX2l0ZXJlbmNvZGUgPSBjX21ha2VfZW5jb2RlcigKICAgICAgICAgICAgICAgIG1hcmtlcnMsIHNlbGYuZGVmYXVsdCwgX2VuY29kZXIsIHNlbGYuaW5kZW50LAogICAgICAgICAgICAgICAgc2VsZi5rZXlfc2VwYXJhdG9yLCBzZWxmLml0ZW1fc2VwYXJhdG9yLCBzZWxmLnNvcnRfa2V5cywKICAgICAgICAgICAgICAgIHNlbGYuc2tpcGtleXMsIHNlbGYuYWxsb3dfbmFuKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIF9pdGVyZW5jb2RlID0gX21ha2VfaXRlcmVuY29kZSgKICAgICAgICAgICAgICAgIG1hcmtlcnMsIHNlbGYuZGVmYXVsdCwgX2VuY29kZXIsIHNlbGYuaW5kZW50LCBmbG9hdHN0ciwKICAgICAgICAgICAgICAgIHNlbGYua2V5X3NlcGFyYXRvciwgc2VsZi5pdGVtX3NlcGFyYXRvciwgc2VsZi5zb3J0X2tleXMsCiAgICAgICAgICAgICAgICBzZWxmLnNraXBrZXlzLCBfb25lX3Nob3QpCgogICAgICAgIHJldHVybiBfaXRlcmVuY29kZShvLCAwKQogICAgICAgIApkYXRhID0geydhJzogeydiJzogeydjJzogMX19fSAgICAgICAgCnByaW50IHJlcHIoanNvbi5kdW1wcyhkYXRhLCBjbHM9Q3VzdG9tSlNPTkVuY29kZXIsIGluZGVudD0nXHQnKSk=