Commits

Olemis Lang committed f596635

GViz QL [ refs #299 ] : OPTION no_values implemented in FORMAT (untested) and OPTION (tested) clauses ... (failures=1)

... as a side-effect GVizClauseHandler.transform method now receives the GViz QL expression object as third arg

Comments (0)

Files changed (2)

trac-dev/gviz/tracgviz/gvizql.py

     Nothing to do by default.
     """
 
-  def transform(self, schema, data):
+  def transform(self, schema, data, expr):
     r"""Transform the result set as dictated by the clause included 
     in the GViz QL expression provided by the client. This 
     transformation *SHOULD* be performed by using iterators.
     # Activate select clause. May be turned off e.g. by PIVOT clause
     self.active = True
 
-  def transform(self, schema, data):
+  def transform(self, schema, data, expr):
     r"""Arrange and transform values considering the given expressions list.
     """
     cols = self.cols_mapping
     # FIXME: str(colnm) => colnm.encode('utf-8')
     self.basetable = name['schema'](lambda colnm: (str(colnm), None))[0]
 
-  def transform(self, schema, data):
+  def transform(self, schema, data, expr):
     r"""Notify that base table has not been processed by data source. 
     This is made this way since it may hide a bug in the underlying 
     data source implementation.
     # FIXME: str(colnm) => colnm.encode('utf-8')
     self.filter = self._resolve_schema(expr, lambda colnm: (str(colnm), None))[0]
 
-  def transform(self, schema, data):
+  def transform(self, schema, data, expr):
     r"""Filter rows that do not satisfy target predicate.
     """
     get_col_value = self._column_accessor(schema)
     self.aggregate = [self._resolve_schema(c, lambda colnm: (str(colnm), None))[0] 
         for c in self.groups_def ]
 
-  def transform(self, schema, data):
+  def transform(self, schema, data, expr):
     r"""Create groups.
     """
     get_col_value = self._column_accessor(schema)
 
   MSG_NOAGG = 'Cannot use PIVOT when no aggregations are defined in SELECT.'
 
-  def transform(self, schema, data):
+  def transform(self, schema, data, expr):
     r"""Transpose tha data table considering the details of SELECT clause
     """
     if self.select_handler is None:
         (self._resolve_schema(c, lambda colnm: (colnm.encode('utf-8'), None))[0],
          is_asc) for c, is_asc in self.order_def ]
 
-  def transform(self, schema, data):
+  def transform(self, schema, data, expr):
     r"""Sort rows in base result set by evaluating target expressions.
     """
     get_col_value = self._column_accessor(schema)
     """
     self.cnt = number
 
-  def transform(self, schema, data):
+  def transform(self, schema, data, expr):
     r"""Retrieve no more than `cnt` items.
     """
     return schema, islice(data, self.cnt)
     """
     self.skip = number
 
-  def transform(self, schema, data):
+  def transform(self, schema, data, expr):
     r"""Skip the number of items determined by `skip` attribute.
     """
     return schema, islice(data, self.skip, None)
       seq = Sequence([seq])
     self.labels = seq
 
-  def transform(self, schema, data):
+  def transform(self, schema, data, expr):
     r"""(Add | modify) the schema in order to (include | update) 
     column labels.
 
     """
     supported = False
     if coltype == 'boolean':
+      if formatter is None:
+        # e.g. GViz no_values option set
+        formatter = ('true', 'false')
       # Formatter is a binary tuple
       idx = 0 if bool(value) else 1
       return formatter[idx]
-      supported = True
+    elif formatter is None:
+      # e.g. GViz no_values option set
+      return to_unicode(value, 'utf8')
     elif coltype in cls.DATETIME_CONVERTER:
       value = cls.DATETIME_CONVERTER[coltype](value)
       supported = True
     else:
       raise GVizRuntimeError("Format not supported for %s type" % (coltype,))
 
-  def transform(self, schema, data):
+  def transform(self, schema, data, expr):
     r"""Annotate result set with formatted values. In practice this means
     to transform data set into (value, formatted_value) tuples.
     """
         for colnm, p in self.fmt)
 
     #raise ValueError('\n'.join([str(patterns), str(schema), str(list(data))]))
-    new_data = ([val if val is None or col[0] not in patterns else \
-                        (val, self.format_value(val, col[1], patterns[col[0]]))\
-                    for val, col in izip(row, schema)] for row in data)
+    new_data = ([val if val is None or not (self.no_values or col[0] in patterns)
+                     else (None if self.no_values else val, 
+                           self.format_value(val, col[1], 
+                                             patterns.get(col[0]))) \
+                 for val, col in izip(row, schema)] for row in data)
     return schema, new_data
 
 class GVizOptionsClause(GVizQLClauseHandler):
         raise GVizInvalidQuery('Contradictory options no_value and no_format')
     self.opts = seq
 
-  def transform(self, schema, data):
-    r"""No transformations applied
+  def _contains(self, optnm):
+    for o,v in self.opts:
+      if o == optnm:
+        return True
+    else:
+      return False
+
+  def transform(self, schema, data, expr):
+    r"""Apply no_values option in the absence of FORMAT clause
     """
-    return schema, data
+    if hasattr(expr, 'fmt') or not self._contains('no_values'):
+      # No need to apply options behavior
+      return schema, data
+    else:
+      # Bare values , assume naive formatting strategy
+      return schema, ([(None, to_unicode(val, 'utf8')) for val in row]
+                      for row in data)
 
 #------------------------------------------------------
 #   GVizQL parsing and compilation
     for ch in self.itereval():
       if options:
         ch.configure(options)
-      schema, data = ch.transform(schema, data)
+      schema, data = ch.transform(schema, data, self)
     return schema, data
 
 #------------------------------------------------------

trac-dev/gviz/tracgviz/testing/test_gvizql.py

       salary number
       isSenior boolean
       = Row =
-         dept = (None, 'Eng')
-         salary = (None, '1000')
-         isSenior = (None, 'true')
-      = Row =
-         dept = (None, 'Eng')
-         salary = (None, '500')
-         isSenior = (None,'false')
-      = Row =
-         dept = (None, 'Eng')
-         salary = (None, '600')
-         isSenior = (None, 'false')
-      = Row =
-         dept = (None, 'Sales')
-         salary = (None, '400')
-         isSenior = (None,'true')
-      = Row =
-         dept = (None, 'Sales')
-         salary = (None, '350')
-         isSenior = (None,'false')
-      = Row =
-         dept = (None, 'Marketing')
-         salary = (None, '800')
-         isSenior = (None, 'true')
+         dept = (None, u'Eng')
+         salary = (None, u'1000')
+         isSenior = (None, u'True')
+      = Row =
+         dept = (None, u'Eng')
+         salary = (None, u'500')
+         isSenior = (None, u'False')
+      = Row =
+         dept = (None, u'Eng')
+         salary = (None, u'600')
+         isSenior = (None, u'False')
+      = Row =
+         dept = (None, u'Sales')
+         salary = (None, u'400')
+         isSenior = (None, u'True')
+      = Row =
+         dept = (None, u'Sales')
+         salary = (None, u'350')
+         isSenior = (None, u'False')
+      = Row =
+         dept = (None, u'Marketing')
+         salary = (None, u'800')
+         isSenior = (None, u'True')
 
 
       >>> parse("select `email address`, name, `date` options no_values", \