trac-gviz / trac-dev / gviz / tracgviz / aggregate.py

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

# Copyright 2009-2011 Olemis Lang <olemis at gmail.com>
#
#   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
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

r"""Aggregation functions defined by Google Visualization API (version 7.0)

https://developers.google.com/chart/interactive/docs/querylanguage#aggregation_functions

Copyright 2009-2011 Olemis Lang <olemis at gmail.com>
Licensed under the Apache License, Version 2.0 
"""
__author__ = 'Olemis Lang'
__all__ = ['agg_' + nm for nm in 'avg count max min sum'.split()]

from itertools import count, ifilter, izip
from math import fsum

from tracgviz.api import GVizRuntimeError

def notimpl(*args, **kwds):
  raise NotImplementedError('Aggregation not supported ... yet')

def _iter_col(rows, getvalue, colnm):
  # FIXME: Always wrap using ifilter ?
  return ifilter(lambda x: x is not None, (getvalue(r, colnm) for r in rows))

def agg_avg(rows, getvalue, colnm):
  # Ignore null values
  dataset = _iter_col(rows, getvalue, colnm)
  c = [0]
  try:
    s = fsum(c.__setitem__(0, idx) or value \
        for idx, value in izip(count(1), dataset))
  except TypeError:
    raise GVizRuntimeError('Numeric column is required')
  c = c[0]
  return None if c == 0 else s/c

agg_avg.return_type = 'number'
agg_avg.types = ('number',)

def agg_count(rows, getvalue, colnm):
  idx = 0
  dataset = _iter_col(rows, getvalue, colnm)
  for idx, _ in izip(count(1), dataset):
    pass
  return idx

agg_count.return_type = 'number'

def agg_max(rows, getvalue, colnm):
  dataset = _iter_col(rows, getvalue, colnm)
  try:
    return max(dataset)
  except ValueError:
    # max() arg is an empty sequence
    return None

def agg_min(rows, getvalue, colnm):
  dataset = _iter_col(rows, getvalue, colnm)
  try:
    return min(dataset)
  except ValueError:
    # max() arg is an empty sequence
    return None

def agg_sum(rows, getvalue, colnm):
  dataset = _iter_col(rows, getvalue, colnm)
  try:
    return fsum(dataset)
  except TypeError:
    raise GVizRuntimeError('Numeric column is required')

agg_sum.return_type = 'number'
agg_sum.types = ('number',)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.