Source code for robot.htmldata.jsonwriter

#  Copyright 2008-2015 Nokia Networks
#  Copyright 2016-     Robot Framework Foundation
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  See the License for the specific language governing permissions and
#  limitations under the License.

[docs] class JsonWriter: def __init__(self, output, separator=''): self._writer = JsonDumper(output) self._separator = separator
[docs] def write_json(self, prefix, data, postfix=';\n', mapping=None, separator=True): self._writer.write(prefix) self._writer.dump(data, mapping) self._writer.write(postfix) self._write_separator(separator)
[docs] def write(self, string, postfix=';\n', separator=True): self._writer.write(string + postfix) self._write_separator(separator)
def _write_separator(self, separator): if separator and self._separator: self._writer.write(self._separator)
[docs] class JsonDumper: def __init__(self, output): self.write = output.write self._dumpers = (MappingDumper(self), IntegerDumper(self), TupleListDumper(self), StringDumper(self), NoneDumper(self), DictDumper(self))
[docs] def dump(self, data, mapping=None): for dumper in self._dumpers: if dumper.handles(data, mapping): dumper.dump(data, mapping) return raise ValueError('Dumping %s not supported.' % type(data))
class _Dumper: _handled_types = None def __init__(self, jsondumper): self._dump = jsondumper.dump self._write = jsondumper.write def handles(self, data, mapping): return isinstance(data, self._handled_types) def dump(self, data, mapping): raise NotImplementedError
[docs] class StringDumper(_Dumper): _handled_types = str _search_and_replace = [('\\', '\\\\'), ('"', '\\"'), ('\t', '\\t'), ('\n', '\\n'), ('\r', '\\r'), ('</', '\\x3c/')]
[docs] def dump(self, data, mapping): self._write('"%s"' % (self._escape(data) if data else ''))
def _escape(self, string): for search, replace in self._search_and_replace: if search in string: string = string.replace(search, replace) return string
[docs] class IntegerDumper(_Dumper): # Handles also bool _handled_types = int
[docs] def dump(self, data, mapping): self._write(str(data).lower())
[docs] class DictDumper(_Dumper): _handled_types = dict
[docs] def dump(self, data, mapping): write = self._write dump = self._dump write('{') last_index = len(data) - 1 for index, key in enumerate(sorted(data)): dump(key, mapping) write(':') dump(data[key], mapping) if index < last_index: write(',') write('}')
[docs] class TupleListDumper(_Dumper): _handled_types = (tuple, list)
[docs] def dump(self, data, mapping): write = self._write dump = self._dump write('[') last_index = len(data) - 1 for index, item in enumerate(data): dump(item, mapping) if index < last_index: write(',') write(']')
[docs] class MappingDumper(_Dumper):
[docs] def handles(self, data, mapping): try: return mapping and data in mapping except TypeError: return False
[docs] def dump(self, data, mapping): self._write(mapping[data])
[docs] class NoneDumper(_Dumper):
[docs] def handles(self, data, mapping): return data is None
[docs] def dump(self, data, mapping): self._write('null')