Revision: f1afea234f73
Author:   Pekka Klärck
Date:     Tue Jun 21 15:04:21 2011
Log: json dump: remove strings and integers for real after removing keywords
http://code.google.com/p/robotframework/source/detail?r=f1afea234f73

Modified:
 /src/robot/result/json.py
 /src/robot/result/jsondatamodel.py
 /utest/result/test_js_serializer.py

=======================================
--- /src/robot/result/json.py   Tue Jun 21 12:33:07 2011
+++ /src/robot/result/json.py   Tue Jun 21 15:04:21 2011
@@ -35,30 +35,30 @@
     string = string.replace('\t', '\\t')
     return '"%s"' % ''.join(get_matching_char(c) for c in string)

-def json_dump(data, output, mappings=None):
+def json_dump(data, output, mapping=None):
     if data is None:
         output.write('null')
-    elif isinstance(data, (int, long)):
-        output.write(str(data))
-    elif isinstance(data, basestring):
-        output.write(encode_basestring(data))
-    elif isinstance(data, list):
-        output.write('[')
-        for index, item in enumerate(data):
-            json_dump(item, output, mappings)
-            if index < len(data)-1:
-                output.write(',')
-        output.write(']')
     elif isinstance(data, dict):
         output.write('{')
-        for index, item in enumerate(data.items()):
-            json_dump(item[0], output, mappings)
+        for index, key in enumerate(data):
+            json_dump(key, output, mapping)
             output.write(':')
-            json_dump(item[1], output, mappings)
+            json_dump(data[key], output, mapping)
             if index < len(data)-1:
                 output.write(',')
         output.write('}')
-    elif mappings and data in mappings:
-        output.write(mappings[data])
+    elif isinstance(data, (list, tuple)):
+        output.write('[')
+        for index, item in enumerate(data):
+            json_dump(item, output, mapping)
+            if index < len(data)-1:
+                output.write(',')
+        output.write(']')
+    elif mapping and data in mapping:
+        json_dump(mapping[data], output)
+    elif isinstance(data, (int, long)):
+        output.write(str(data))
+    elif isinstance(data, basestring):
+        output.write(encode_basestring(data))
     else:
raise Exception('Data type (%s) serialization not supported' % type(data))
=======================================
--- /src/robot/result/jsondatamodel.py  Tue Jun 21 13:22:00 2011
+++ /src/robot/result/jsondatamodel.py  Tue Jun 21 15:04:21 2011
@@ -20,12 +20,11 @@

 class DataModel(object):

-    UNUSED_STRING = object()
-
     def __init__(self, robot_data):
         self._robot_data = robot_data
         self._settings = None
         self._set_generated(time.localtime())
+        self._index_remap = {}

     def _set_generated(self, timetuple):
         genMillis = long(time.mktime(timetuple) * 1000) -\
@@ -40,14 +39,14 @@
     def set_settings(self, settings):
         self._settings = settings

-    def write_to(self, output):
-        output.write('var u = "";\n')
- self._dump_json('window.output = ', self._robot_data, output, {DataModel.UNUSED_STRING:'u'})
+    def write_to(self, output, mapping=None):
+        self._dump_json('window.output = ', self._robot_data, output,
+                        self._index_remap)
         self._dump_json('window.settings = ', self._settings, output)

-    def _dump_json(self, name, data, output, mappings=None):
+    def _dump_json(self, name, data, output, mapping=None):
         output.write(name)
-        json.json_dump(data, output, mappings)
+        json.json_dump(data, output, mapping)
         output.write(';\n')

     def remove_keywords(self):
@@ -69,8 +68,22 @@

     def _prune_unused_indices(self):
         used = self._collect_used_indices(self._robot_data['suite'], set())
- self._robot_data['strings'] = [text if index in used else DataModel.UNUSED_STRING for index, text in enumerate(self._robot_data['strings'])] - self._robot_data['integers'] = [number if (-1 -index) in used else 0 for index, number in enumerate(self._robot_data['integers'])]
+        self._robot_data['strings'] = \
+            list(self._prune(self._robot_data['strings'], used))
+        self._robot_data['integers'] = \
+            list(self._prune(self._robot_data['integers'], used,
+                             map_index=lambda index: -1 - index,
+                             offset_increment=-1))
+
+    def _prune(self, data, used, map_index=None, offset_increment=1):
+        offset = 0
+        for index, text in enumerate(data):
+            index = map_index(index) if map_index else index
+            if index in used:
+                self._index_remap[index] = index - offset
+                yield text
+            else:
+                offset += offset_increment

     def _collect_used_indices(self, data, result):
         for item in data:
=======================================
--- /utest/result/test_js_serializer.py Tue Jun 21 13:22:00 2011
+++ /utest/result/test_js_serializer.py Tue Jun 21 15:04:21 2011
@@ -18,6 +18,10 @@
 from robot.result.elementhandlers import Context
from robot.utils.asserts import assert_equals, assert_true, assert_not_equals, assert_false

+
+# TODO: Split this monster test suite.
+# At least json_dump tests should be moved to their own module.
+
 class TestJsSerializer(unittest.TestCase):

     SUITE_XML = """
@@ -118,8 +122,10 @@
             self._assert_plain_suite(data_model, plain_suite)

     def assert_model_does_not_contain(self, data_model, items):
- self._check_does_not_contain(self._reverse_from_ids(data_model, data_model._robot_data['suite']),
-            ['*'+i for i in items])
+        suite = self._reverse_from_ids(data_model,
+                                       data_model._robot_data['suite'],
+                                       data_model._index_remap)
+        self._check_does_not_contain(suite, ['*'+i for i in items])

     def _check_does_not_contain(self, suite, items):
         for item in suite:
@@ -131,18 +137,18 @@
reversed = self._reverse_from_ids(data_model, data_model._robot_data['suite'])
         assert_equals(reversed, plain_suite)

-    def _reverse_from_ids(self, data_model, suite):
-        if isinstance(suite, (int, long)):
-            return self._reverse_id(data_model, suite)
-        result = []
-        for entry in suite:
-            if isinstance(entry, list):
-                result += [self._reverse_from_ids(data_model, entry)]
-            elif isinstance(entry, dict):
- result += [dict((self._reverse_from_ids(data_model, key), self._reverse_from_ids(data_model, value)) for key, value in entry.items())]
-            else:
-                result += [self._reverse_id(data_model, entry)]
-        return result
+    def _reverse_from_ids(self, data, item, remap={}):
+        recurse = self._reverse_from_ids
+        if isinstance(item, (int, long)):
+            if item in remap:
+                item = remap[item]
+            return self._reverse_id(data, item)
+        if isinstance(item, list):
+            return [recurse(data, i, remap) for i in item]
+        if isinstance(item, dict):
+            return dict((recurse(data, k, remap),
+                         recurse(data, item[k], remap)) for k in item)
+        raise AssertionError('Unexpected item %r' % item)

     def _reverse_id(self, data_model, id):
         if id is None:
@@ -259,7 +265,7 @@
assert_true(integers_before > self._list_size(data_model._robot_data['integers']))

     def _list_size(self, array):
- return len(''.join(str(val) if val != DataModel.UNUSED_STRING else 'u' for val in array))
+        return len(''.join(str(val) for val in array))

     def test_suite_xml_parsing(self):
         # Tests parsing the whole suite structure
@@ -357,8 +363,9 @@
         buffer = StringIO.StringIO()
         mapped1 = object()
         mapped2 = object()
- json_dump([mapped1, [mapped2, {mapped2:mapped1}]], buffer, {mapped1:'1', mapped2:'a'})
-        assert_equals('[1,[a,{a:1}]]', buffer.getvalue())
+        json_dump([mapped1, [mapped2, {mapped2:mapped1}]], buffer,
+                  mapping={mapped1:'1', mapped2:'a'})
+        assert_equals('["1",["a",{"a":"1"}]]', buffer.getvalue())

     def _get_data_model(self, xml_string):
sax.parseString('<robot generator="test">%s<statistics/><errors/></robot>' % xml_string, self._handler)

Reply via email to