app/gviz/gviz_api_test.py
changeset 2373 05ab9393303d
equal deleted inserted replaced
2371:805400745f57 2373:05ab9393303d
       
     1 #!/usr/bin/python
       
     2 #
       
     3 # Copyright (C) 2008 Google Inc.
       
     4 #
       
     5 # Licensed under the Apache License, Version 2.0 (the "License");
       
     6 # you may not use this file except in compliance with the License.
       
     7 # You may obtain a copy of the License at
       
     8 #
       
     9 #      http://www.apache.org/licenses/LICENSE-2.0
       
    10 #
       
    11 # Unless required by applicable law or agreed to in writing, software
       
    12 # distributed under the License is distributed on an "AS IS" BASIS,
       
    13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    14 # See the License for the specific language governing permissions and
       
    15 # limitations under the License.
       
    16 
       
    17 """Tests for the gviz_api module."""
       
    18 
       
    19 __author__ = "Amit Weinstein"
       
    20 
       
    21 from datetime import date
       
    22 from datetime import datetime
       
    23 from datetime import time
       
    24 import re
       
    25 import unittest
       
    26 
       
    27 from gviz_api import DataTable
       
    28 from gviz_api import DataTableException
       
    29 
       
    30 
       
    31 class DataTableTest(unittest.TestCase):
       
    32 
       
    33   def testSingleValueToJS(self):
       
    34     # We first check that given an unknown type it raises exception
       
    35     self.assertRaises(DataTableException,
       
    36                       DataTable.SingleValueToJS, 1, "no_such_type")
       
    37 
       
    38     # If we give a type which does not match the value, we expect it to fail
       
    39     self.assertRaises(DataTableException,
       
    40                       DataTable.SingleValueToJS, "a", "number")
       
    41     self.assertRaises(DataTableException,
       
    42                       DataTable.SingleValueToJS, "b", "timeofday")
       
    43     self.assertRaises(DataTableException,
       
    44                       DataTable.SingleValueToJS, 10, "date")
       
    45 
       
    46     # A tuple for value and formatted value should be of length 2
       
    47     self.assertRaises(DataTableException,
       
    48                       DataTable.SingleValueToJS, (5, "5$", "6$"), "string")
       
    49 
       
    50     # Some good examples from all the different types
       
    51     self.assertEqual("true", DataTable.SingleValueToJS(True, "boolean"))
       
    52     self.assertEqual("false", DataTable.SingleValueToJS(False, "boolean"))
       
    53     self.assertEqual("true", DataTable.SingleValueToJS(1, "boolean"))
       
    54     self.assertEqual("null", DataTable.SingleValueToJS(None, "boolean"))
       
    55     self.assertEqual(("false", "'a'"),
       
    56                      DataTable.SingleValueToJS((False, "a"), "boolean"))
       
    57 
       
    58     self.assertEqual("1", DataTable.SingleValueToJS(1, "number"))
       
    59     self.assertEqual("1.0", DataTable.SingleValueToJS(1., "number"))
       
    60     self.assertEqual("-5", DataTable.SingleValueToJS(-5, "number"))
       
    61     self.assertEqual("null", DataTable.SingleValueToJS(None, "number"))
       
    62     self.assertEqual(("5", "'5$'"),
       
    63                      DataTable.SingleValueToJS((5, "5$"), "number"))
       
    64 
       
    65     self.assertEqual("'-5'", DataTable.SingleValueToJS(-5, "string"))
       
    66     self.assertEqual("'abc'", DataTable.SingleValueToJS("abc", "string"))
       
    67     self.assertEqual("null", DataTable.SingleValueToJS(None, "string"))
       
    68 
       
    69     self.assertEqual("new Date(2010,0,2)",
       
    70                      DataTable.SingleValueToJS(date(2010, 1, 2), "date"))
       
    71     self.assertEqual("new Date(2001,1,3)",
       
    72                      DataTable.SingleValueToJS(datetime(2001, 2, 3, 4, 5, 6),
       
    73                                                "date"))
       
    74     self.assertEqual("null", DataTable.SingleValueToJS(None, "date"))
       
    75 
       
    76     self.assertEqual("[10,11,12]",
       
    77                      DataTable.SingleValueToJS(time(10, 11, 12), "timeofday"))
       
    78     self.assertEqual("[3,4,5]",
       
    79                      DataTable.SingleValueToJS(datetime(2010, 1, 2, 3, 4, 5),
       
    80                                                "timeofday"))
       
    81     self.assertEqual("null", DataTable.SingleValueToJS(None, "timeofday"))
       
    82 
       
    83     self.assertEqual("new Date(2001,1,3,4,5,6)",
       
    84                      DataTable.SingleValueToJS(datetime(2001, 2, 3, 4, 5, 6),
       
    85                                                "datetime"))
       
    86     self.assertEqual("null", DataTable.SingleValueToJS(None, "datetime"))
       
    87     self.assertEqual(("null", "'none'"),
       
    88                      DataTable.SingleValueToJS((None, "none"), "string"))
       
    89 
       
    90   def testDifferentStrings(self):
       
    91     # Checking escaping of strings
       
    92     problematic_strings = ["control", "new\nline", "",
       
    93                            "single'quote", 'double"quote',
       
    94                            r"one\slash", r"two\\slash", u"unicode eng",
       
    95                            u"unicode \u05e2\u05d1\u05e8\u05d9\u05ea"]
       
    96     for s in problematic_strings:
       
    97       js_value = DataTable.SingleValueToJS(s, "string")
       
    98       if isinstance(js_value, unicode):
       
    99         js_value = "u%s" % js_value
       
   100       self.assertEquals(s, eval(js_value))
       
   101 
       
   102       js_value = DataTable.SingleValueToJS(("str", s), "string")[1]
       
   103       if isinstance(js_value, unicode):
       
   104         js_value = "u%s" % js_value
       
   105       self.assertEquals(s, eval(js_value))
       
   106 
       
   107   def testDifferentCustomProperties(self):
       
   108     # Checking escaping of custom properties
       
   109     problematic_cps = [{"control": "test"}, {u"unicode": "value"},
       
   110                        {"key": u"unicode"}, {u"unicode": u"unicode"},
       
   111                        {"regular": "single'quote"}, {"unicode": u"s'quote"}]
       
   112     for cp in problematic_cps:
       
   113       js_value = DataTable._EscapeCustomProperties(cp)
       
   114       self.assertEquals(cp, eval(js_value))
       
   115 
       
   116   def testColumnTypeParser(self):
       
   117     # Checking several wrong formats
       
   118     self.assertRaises(DataTableException,
       
   119                       DataTable.ColumnTypeParser, 5)
       
   120     self.assertRaises(DataTableException,
       
   121                       DataTable.ColumnTypeParser, ("a", "b", "c", "d"))
       
   122     self.assertRaises(DataTableException,
       
   123                       DataTable.ColumnTypeParser, ("a", 5, "c"))
       
   124 
       
   125     # Checking several legal formats
       
   126     self.assertEqual({"id": "abc", "label": "abc", "type": "string",
       
   127                       "custom_properties": {}},
       
   128                      DataTable.ColumnTypeParser("abc"))
       
   129     self.assertEqual({"id": "abc", "label": "abc", "type": "string",
       
   130                       "custom_properties": {}},
       
   131                      DataTable.ColumnTypeParser(("abc",)))
       
   132     self.assertEqual({"id": "abc", "label": "bcd", "type": "string",
       
   133                       "custom_properties": {}},
       
   134                      DataTable.ColumnTypeParser(("abc", "string", "bcd")))
       
   135     self.assertEqual({"id": "a", "label": "b", "type": "number",
       
   136                       "custom_properties": {}},
       
   137                      DataTable.ColumnTypeParser(("a", "number", "b")))
       
   138     self.assertEqual({"id": "a", "label": "a", "type": "number",
       
   139                       "custom_properties": {}},
       
   140                      DataTable.ColumnTypeParser(("a", "number")))
       
   141     self.assertEqual({"id": "i", "label": "l", "type": "string",
       
   142                       "custom_properties": {"key": "value"}},
       
   143                      DataTable.ColumnTypeParser(("i", "string", "l",
       
   144                                                  {"key": "value"})))
       
   145 
       
   146   def testTableDescriptionParser(self):
       
   147     # We expect it to fail with empty lists or dictionaries
       
   148     self.assertRaises(DataTableException,
       
   149                       DataTable.TableDescriptionParser, {})
       
   150     self.assertRaises(DataTableException,
       
   151                       DataTable.TableDescriptionParser, [])
       
   152     self.assertRaises(DataTableException,
       
   153                       DataTable.TableDescriptionParser, {"a": []})
       
   154     self.assertRaises(DataTableException,
       
   155                       DataTable.TableDescriptionParser, {"a": {"b": {}}})
       
   156 
       
   157     # We expect it to fail if we give a non-string at the lowest level
       
   158     self.assertRaises(DataTableException,
       
   159                       DataTable.TableDescriptionParser, {"a": 5})
       
   160     self.assertRaises(DataTableException,
       
   161                       DataTable.TableDescriptionParser, [("a", "number"), 6])
       
   162 
       
   163     # Some valid examples which mixes both dictionaries and lists
       
   164     self.assertEqual(
       
   165         [{"id": "a", "label": "a", "type": "date",
       
   166           "depth": 0, "container": "iter", "custom_properties": {}},
       
   167          {"id": "b", "label": "b", "type": "timeofday",
       
   168           "depth": 0, "container": "iter", "custom_properties": {}}],
       
   169         DataTable.TableDescriptionParser([("a", "date"), ("b", "timeofday")]))
       
   170 
       
   171     self.assertEqual(
       
   172         [{"id": "a", "label": "a", "type": "string",
       
   173           "depth": 0, "container": "dict", "custom_properties": {}},
       
   174          {"id": "b", "label": "b", "type": "number",
       
   175           "depth": 1, "container": "iter", "custom_properties": {}},
       
   176          {"id": "c", "label": "column c", "type": "string",
       
   177           "depth": 1, "container": "iter", "custom_properties": {}}],
       
   178         DataTable.TableDescriptionParser({"a": [("b", "number"),
       
   179                                                 ("c", "string", "column c")]}))
       
   180 
       
   181     self.assertEqual(
       
   182         [{"id": "a", "label": "column a", "type": "number",
       
   183           "depth": 0, "container": "dict", "custom_properties": {}},
       
   184          {"id": "b", "label": "b", "type": "number",
       
   185           "depth": 1, "container": "dict", "custom_properties": {}},
       
   186          {"id": "c", "label": "c", "type": "string",
       
   187           "depth": 1, "container": "dict", "custom_properties": {}}],
       
   188         DataTable.TableDescriptionParser({("a", "number", "column a"):
       
   189                                           {"b": "number", "c": "string"}}))
       
   190 
       
   191     self.assertEqual(
       
   192         [{"id": "a", "label": "column a", "type": "number",
       
   193           "depth": 0, "container": "dict", "custom_properties": {}},
       
   194          {"id": "b", "label": "column b", "type": "string",
       
   195           "depth": 1, "container": "scalar", "custom_properties": {}}],
       
   196         DataTable.TableDescriptionParser({("a", "number", "column a"):
       
   197                                           ("b", "string", "column b")}))
       
   198 
       
   199   def testAppendData(self):
       
   200     # We check a few examples where the format of the data does not match the
       
   201     # description and hen a few valid examples. The test for the content itself
       
   202     # is done inside the ToJSCode and ToJSon functions.
       
   203     table = DataTable([("a", "number"), ("b", "string")])
       
   204     self.assertEqual(0, table.NumberOfRows())
       
   205     self.assertRaises(DataTableException,
       
   206                       table.AppendData, [[1, "a", True]])
       
   207     self.assertRaises(DataTableException,
       
   208                       table.AppendData, {1: ["a"], 2: ["b"]})
       
   209     self.assertEquals(None, table.AppendData([[1, "a"], [2, "b"]]))
       
   210     self.assertEqual(2, table.NumberOfRows())
       
   211     self.assertEquals(None, table.AppendData([[3, "c"], [4]]))
       
   212     self.assertEqual(4, table.NumberOfRows())
       
   213 
       
   214     table = DataTable({"a": "number", "b": "string"})
       
   215     self.assertEqual(0, table.NumberOfRows())
       
   216     self.assertRaises(DataTableException,
       
   217                       table.AppendData, [[1, "a"]])
       
   218     self.assertRaises(DataTableException,
       
   219                       table.AppendData, {5: {"b": "z"}})
       
   220     self.assertEquals(None, table.AppendData([{"a": 1, "b": "z"}]))
       
   221     self.assertEqual(1, table.NumberOfRows())
       
   222 
       
   223     table = DataTable({("a", "number"): [("b", "string")]})
       
   224     self.assertEqual(0, table.NumberOfRows())
       
   225     self.assertRaises(DataTableException,
       
   226                       table.AppendData, [[1, "a"]])
       
   227     self.assertRaises(DataTableException,
       
   228                       table.AppendData, {5: {"b": "z"}})
       
   229     self.assertEquals(None, table.AppendData({5: ["z"], 6: ["w"]}))
       
   230     self.assertEqual(2, table.NumberOfRows())
       
   231 
       
   232     table = DataTable({("a", "number"): {"b": "string", "c": "number"}})
       
   233     self.assertEqual(0, table.NumberOfRows())
       
   234     self.assertRaises(DataTableException,
       
   235                       table.AppendData, [[1, "a"]])
       
   236     self.assertRaises(DataTableException,
       
   237                       table.AppendData, {1: ["a", 2]})
       
   238     self.assertEquals(None, table.AppendData({5: {"b": "z", "c": 6},
       
   239                                               7: {"c": 8},
       
   240                                               9: {}}))
       
   241     self.assertEqual(3, table.NumberOfRows())
       
   242 
       
   243   def testToJSCode(self):
       
   244     table = DataTable([("a", "number", "A"), "b", ("c", "timeofday")],
       
   245                       [[1],
       
   246                        [None, "z", time(1, 2, 3)],
       
   247                        [(2, "2$"), "w", time(2, 3, 4)]])
       
   248     self.assertEqual(3, table.NumberOfRows())
       
   249     self.assertEqual(("var mytab = new google.visualization.DataTable();\n"
       
   250                       "mytab.addColumn('number', 'A', 'a');\n"
       
   251                       "mytab.addColumn('string', 'b', 'b');\n"
       
   252                       "mytab.addColumn('timeofday', 'c', 'c');\n"
       
   253                       "mytab.addRows(3);\n"
       
   254                       "mytab.setCell(0, 0, 1);\n"
       
   255                       "mytab.setCell(1, 1, 'z');\n"
       
   256                       "mytab.setCell(1, 2, [1,2,3]);\n"
       
   257                       "mytab.setCell(2, 0, 2, '2$');\n"
       
   258                       "mytab.setCell(2, 1, 'w');\n"
       
   259                       "mytab.setCell(2, 2, [2,3,4]);\n"),
       
   260                      table.ToJSCode("mytab"))
       
   261 
       
   262     table = DataTable({("a", "number"): {"b": "date", "c": "datetime"}},
       
   263                       {1: {},
       
   264                        2: {"b": date(1, 2, 3)},
       
   265                        3: {"c": datetime(1, 2, 3, 4, 5, 6)}})
       
   266     self.assertEqual(3, table.NumberOfRows())
       
   267     self.assertEqual(("var mytab2 = new google.visualization.DataTable();\n"
       
   268                       "mytab2.addColumn('datetime', 'c', 'c');\n"
       
   269                       "mytab2.addColumn('date', 'b', 'b');\n"
       
   270                       "mytab2.addColumn('number', 'a', 'a');\n"
       
   271                       "mytab2.addRows(3);\n"
       
   272                       "mytab2.setCell(0, 2, 1);\n"
       
   273                       "mytab2.setCell(1, 1, new Date(1,1,3));\n"
       
   274                       "mytab2.setCell(1, 2, 2);\n"
       
   275                       "mytab2.setCell(2, 0, new Date(1,1,3,4,5,6));\n"
       
   276                       "mytab2.setCell(2, 2, 3);\n"),
       
   277                      table.ToJSCode("mytab2", columns_order=["c", "b", "a"]))
       
   278 
       
   279   def testToJSon(self):
       
   280     # The json of the initial data we load to the table.
       
   281     init_data_json = ("{cols:"
       
   282                       "[{id:'a',label:'A',type:'number'},"
       
   283                       "{id:'b',label:'b',type:'string'},"
       
   284                       "{id:'c',label:'c',type:'boolean'}],"
       
   285                       "rows:["
       
   286                       "{c:[{v:1},,{v:null}]},"
       
   287                       "{c:[,{v:'z'},{v:true}]}"
       
   288                       "]}")
       
   289     table = DataTable([("a", "number", "A"), "b", ("c", "boolean")],
       
   290                       [[1],
       
   291                        [None, "z", True]])
       
   292     self.assertEqual(2, table.NumberOfRows())
       
   293     self.assertEqual(init_data_json,
       
   294                      table.ToJSon())
       
   295     table.AppendData([[-1, "w", False]])
       
   296     self.assertEqual(3, table.NumberOfRows())
       
   297     self.assertEqual(init_data_json[:-2] + ",{c:[{v:-1},{v:'w'},{v:false}]}]}",
       
   298                      table.ToJSon())
       
   299 
       
   300     cols_json = ("{cols:"
       
   301                  "[{id:'t',label:'T',type:'timeofday'},"
       
   302                  "{id:'d',label:'d',type:'date'},"
       
   303                  "{id:'dt',label:'dt',type:'datetime'}],")
       
   304     table = DataTable({("d", "date"): [("t", "timeofday", "T"),
       
   305                                        ("dt", "datetime")]})
       
   306     table.LoadData({date(1, 2, 3): [time(1, 2, 3)]})
       
   307     self.assertEqual(1, table.NumberOfRows())
       
   308     self.assertEqual(cols_json +
       
   309                      "rows:[{c:[{v:[1,2,3]},{v:new Date(1,1,3)},{v:null}]}]}",
       
   310                      table.ToJSon(columns_order=["t", "d", "dt"]))
       
   311     table.LoadData({date(2, 3, 4): [(time(2, 3, 4), "time 2 3 4"),
       
   312                                     datetime(1, 2, 3, 4, 5, 6)],
       
   313                     date(3, 4, 5): []})
       
   314     self.assertEqual(2, table.NumberOfRows())
       
   315     self.assertEqual((cols_json + "rows:["
       
   316                       "{c:[{v:[2,3,4],f:'time 2 3 4'},{v:new Date(2,2,4)},"
       
   317                       "{v:new Date(1,1,3,4,5,6)}]},"
       
   318                       "{c:[,{v:new Date(3,3,5)},{v:null}]}]}"),
       
   319                      table.ToJSon(columns_order=["t", "d", "dt"]))
       
   320 
       
   321     json = ("{cols:[{id:'a',label:'a',type:'string'},"
       
   322             "{id:'b',label:'b',type:'number'}],"
       
   323             "rows:[{c:[{v:'a1'},{v:1}]},{c:[{v:'a2'},{v:2}]},"
       
   324             "{c:[{v:'a3'},{v:3}]}]}")
       
   325     table = DataTable({"a": ("b", "number")},
       
   326                       {"a1": 1, "a2": 2, "a3": 3})
       
   327     self.assertEqual(3, table.NumberOfRows())
       
   328     self.assertEqual(json,
       
   329                      table.ToJSon())
       
   330 
       
   331   def testCustomProperties(self):
       
   332     # The json of the initial data we load to the table.
       
   333     json = ("{cols:"
       
   334             "[{id:'a',label:'A',type:'number',p:{'col_cp':'col_v'}},"
       
   335             "{id:'b',label:'b',type:'string'},"
       
   336             "{id:'c',label:'c',type:'boolean'}],"
       
   337             "rows:["
       
   338             "{c:[{v:1},,{v:null,p:{'null_cp':'null_v'}}],p:{'row_cp':'row_v'}},"
       
   339             "{c:[,{v:'z',p:{'cell_cp':'cell_v'}},{v:true}]},"
       
   340             "{c:[{v:3},,{v:null}],p:{'row_cp2':'row_v2'}}],"
       
   341             "p:{'global_cp':'global_v'}"
       
   342             "}")
       
   343     jscode = ("var mytab = new google.visualization.DataTable();\n"
       
   344               "mytab.setTableProperties({'global_cp':'global_v'});\n"
       
   345               "mytab.addColumn('number', 'A', 'a');\n"
       
   346               "mytab.setColumnProperties(0, {'col_cp':'col_v'});\n"
       
   347               "mytab.addColumn('string', 'b', 'b');\n"
       
   348               "mytab.addColumn('boolean', 'c', 'c');\n"
       
   349               "mytab.addRows(3);\n"
       
   350               "mytab.setCell(0, 0, 1);\n"
       
   351               "mytab.setCell(0, 2, null, null, {'null_cp':'null_v'});\n"
       
   352               "mytab.setRowProperties(0, {'row_cp':'row_v'});\n"
       
   353               "mytab.setCell(1, 1, 'z', null, {'cell_cp':'cell_v'});\n"
       
   354               "mytab.setCell(1, 2, true);\n"
       
   355               "mytab.setCell(2, 0, 3);\n"
       
   356               "mytab.setRowProperties(2, {'row_cp2':'row_v2'});\n")
       
   357 
       
   358     table = DataTable([("a", "number", "A", {"col_cp": "col_v"}), "b",
       
   359                        ("c", "boolean")],
       
   360                       custom_properties={"global_cp": "global_v"})
       
   361     table.AppendData([[1, None, (None, None, {"null_cp": "null_v"})]],
       
   362                      custom_properties={"row_cp": "row_v"})
       
   363     table.AppendData([[None, ("z", None, {"cell_cp": "cell_v"}), True], [3]])
       
   364     table.SetRowsCustomProperties(2, {"row_cp2": "row_v2"})
       
   365     self.assertEqual(json, table.ToJSon())
       
   366     self.assertEqual(jscode, table.ToJSCode("mytab"))
       
   367 
       
   368   def testToCsv(self):
       
   369     init_data_csv = "\n".join(['"A", "b", "c"',
       
   370                                '1, "", ""',
       
   371                                '"", "zz\'top", true'])
       
   372     table = DataTable([("a", "number", "A"), "b", ("c", "boolean")],
       
   373                       [[(1, "$1")], [None, "zz'top", True]])
       
   374     self.assertEqual(init_data_csv, table.ToCsv())
       
   375     table.AppendData([[-1, "w", False]])
       
   376     init_data_csv = "%s\n%s" % (init_data_csv, '-1, "w", false')
       
   377     self.assertEquals(init_data_csv, table.ToCsv())
       
   378 
       
   379     init_data_csv = "\n".join([
       
   380         '"T", "d", "dt"',
       
   381         '"[1,2,3]", "new Date(1,1,3)", ""',
       
   382         '"time ""2 3 4""", "new Date(2,2,4)", "new Date(1,1,3,4,5,6)"',
       
   383         '"", "new Date(3,3,5)", ""'])
       
   384     table = DataTable({("d", "date"): [("t", "timeofday", "T"),
       
   385                                        ("dt", "datetime")]})
       
   386     table.LoadData({date(1, 2, 3): [time(1, 2, 3)],
       
   387                     date(2, 3, 4): [(time(2, 3, 4), 'time "2 3 4"'),
       
   388                                     datetime(1, 2, 3, 4, 5, 6)],
       
   389                     date(3, 4, 5): []})
       
   390     self.assertEqual(init_data_csv, table.ToCsv(columns_order=["t", "d", "dt"]))
       
   391 
       
   392   def testToTsvExcel(self):
       
   393     table = DataTable({("d", "date"): [("t", "timeofday", "T"),
       
   394                                        ("dt", "datetime")]})
       
   395     table.LoadData({date(1, 2, 3): [time(1, 2, 3)],
       
   396                     date(2, 3, 4): [(time(2, 3, 4), 'time "2 3 4"'),
       
   397                                     datetime(1, 2, 3, 4, 5, 6)],
       
   398                     date(3, 4, 5): []})
       
   399     self.assertEqual(table.ToCsv().replace(", ", "\t").encode("UTF-16LE"),
       
   400                      table.ToTsvExcel())
       
   401 
       
   402   def testToHtml(self):
       
   403     html_table_header = "<html><body><table border='1'>"
       
   404     html_table_footer = "</table></body></html>"
       
   405     init_data_html = html_table_header + (
       
   406         "<thead><tr>"
       
   407         "<th>A</th><th>b</th><th>c</th>"
       
   408         "</tr></thead>"
       
   409         "<tbody>"
       
   410         "<tr><td>'$1'</td><td></td><td></td></tr>"
       
   411         "<tr><td></td><td>'&lt;z&gt;'</td><td>true</td></tr>"
       
   412         "</tbody>") + html_table_footer
       
   413     table = DataTable([("a", "number", "A"), "b", ("c", "boolean")],
       
   414                       [[(1, "$1")], [None, "<z>", True]])
       
   415     self.assertEqual(init_data_html.replace("\n", ""), table.ToHtml())
       
   416 
       
   417     init_data_html = html_table_header + (
       
   418         "<thead><tr>"
       
   419         "<th>T</th><th>d</th><th>dt</th>"
       
   420         "</tr></thead>"
       
   421         "<tbody>"
       
   422         "<tr><td>[1,2,3]</td><td>new Date(1,1,3)</td><td></td></tr>"
       
   423         "<tr><td>'time 2 3 4'</td><td>new Date(2,2,4)</td>"
       
   424         "<td>new Date(1,1,3,4,5,6)</td></tr>"
       
   425         "<tr><td></td><td>new Date(3,3,5)</td><td></td></tr>"
       
   426         "</tbody>") + html_table_footer
       
   427     table = DataTable({("d", "date"): [("t", "timeofday", "T"),
       
   428                                        ("dt", "datetime")]})
       
   429     table.LoadData({date(1, 2, 3): [time(1, 2, 3)],
       
   430                     date(2, 3, 4): [(time(2, 3, 4), "time 2 3 4"),
       
   431                                     datetime(1, 2, 3, 4, 5, 6)],
       
   432                     date(3, 4, 5): []})
       
   433     self.assertEqual(init_data_html.replace("\n", ""),
       
   434                      table.ToHtml(columns_order=["t", "d", "dt"]))
       
   435 
       
   436   def testOrderBy(self):
       
   437     data = [("b", 3), ("a", 3), ("a", 2), ("b", 1)]
       
   438     description = ["col1", ("col2", "number", "Second Column")]
       
   439     table = DataTable(description, data)
       
   440 
       
   441     table_num_sorted = DataTable(description,
       
   442                                  sorted(data, key=lambda x: (x[1], x[0])))
       
   443 
       
   444     table_str_sorted = DataTable(description,
       
   445                                  sorted(data, key=lambda x: x[0]))
       
   446 
       
   447     table_diff_sorted = DataTable(description,
       
   448                                   sorted(sorted(data, key=lambda x: x[1]),
       
   449                                          key=lambda x: x[0], reverse=True))
       
   450 
       
   451     self.assertEqual(table_num_sorted.ToJSon(),
       
   452                      table.ToJSon(order_by=("col2", "col1")))
       
   453     self.assertEqual(table_num_sorted.ToJSCode("mytab"),
       
   454                      table.ToJSCode("mytab", order_by=("col2", "col1")))
       
   455 
       
   456     self.assertEqual(table_str_sorted.ToJSon(), table.ToJSon(order_by="col1"))
       
   457     self.assertEqual(table_str_sorted.ToJSCode("mytab"),
       
   458                      table.ToJSCode("mytab", order_by="col1"))
       
   459 
       
   460     self.assertEqual(table_diff_sorted.ToJSon(),
       
   461                      table.ToJSon(order_by=[("col1", "desc"), "col2"]))
       
   462     self.assertEqual(table_diff_sorted.ToJSCode("mytab"),
       
   463                      table.ToJSCode("mytab",
       
   464                                     order_by=[("col1", "desc"), "col2"]))
       
   465 
       
   466   def testToJSonResponse(self):
       
   467     description = ["col1", "col2", "col3"]
       
   468     data = [("1", "2", "3"), ("a", "b", "c"), ("One", "Two", "Three")]
       
   469     req_id = 4
       
   470     table = DataTable(description, data)
       
   471 
       
   472     start_str_default = r"google.visualization.Query.setResponse"
       
   473     start_str_handler = r"MyHandlerFunction"
       
   474     default_params = (r"\s*'version'\s*:\s*'0.6'\s*,\s*'reqId'\s*:\s*'%s'\s*,"
       
   475                       r"\s*'status'\s*:\s*'OK'\s*" % req_id)
       
   476     regex1 = re.compile("%s\(\s*\{%s,\s*'table'\s*:\s*{(.*)}\s*\}\s*\);" %
       
   477                         (start_str_default, default_params))
       
   478     regex2 = re.compile("%s\(\s*\{%s,\s*'table'\s*:\s*{(.*)}\s*\}\s*\);" %
       
   479                         (start_str_handler, default_params))
       
   480 
       
   481     json_str = table.ToJSon().strip()
       
   482 
       
   483     json_response = table.ToJSonResponse(req_id=req_id)
       
   484     match = regex1.findall(json_response)
       
   485     self.assertEquals(len(match), 1)
       
   486     # We want to match against the json_str without the curly brackets.
       
   487     self.assertEquals(match[0], json_str[1:-1])
       
   488 
       
   489     json_response = table.ToJSonResponse(req_id=req_id,
       
   490                                          response_handler=start_str_handler)
       
   491     match = regex2.findall(json_response)
       
   492     self.assertEquals(len(match), 1)
       
   493     # We want to match against the json_str without the curly brackets.
       
   494     self.assertEquals(match[0], json_str[1:-1])
       
   495 
       
   496   def testToResponse(self):
       
   497     description = ["col1", "col2", "col3"]
       
   498     data = [("1", "2", "3"), ("a", "b", "c"), ("One", "Two", "Three")]
       
   499     table = DataTable(description, data)
       
   500 
       
   501     self.assertEquals(table.ToResponse(), table.ToJSonResponse())
       
   502     self.assertEquals(table.ToResponse(tqx="out:csv"), table.ToCsv())
       
   503     self.assertEquals(table.ToResponse(tqx="out:html"), table.ToHtml())
       
   504     self.assertRaises(DataTableException, table.ToResponse, tqx="version:0.1")
       
   505     self.assertEquals(table.ToResponse(tqx="reqId:4;responseHandler:handle"),
       
   506                       table.ToJSonResponse(req_id=4, response_handler="handle"))
       
   507     self.assertEquals(table.ToResponse(tqx="out:csv;reqId:4"), table.ToCsv())
       
   508     self.assertEquals(table.ToResponse(order_by="col2"),
       
   509                       table.ToJSonResponse(order_by="col2"))
       
   510     self.assertEquals(table.ToResponse(tqx="out:html",
       
   511                                        columns_order=("col3", "col2", "col1")),
       
   512                       table.ToHtml(columns_order=("col3", "col2", "col1")))
       
   513     self.assertRaises(ValueError, table.ToResponse, tqx="SomeWrongTqxFormat")
       
   514     self.assertRaises(DataTableException, table.ToResponse, tqx="out:bad")
       
   515 
       
   516 
       
   517 if __name__ == "__main__":
       
   518   unittest.main()