Exemplo n.º 1
0
    def _render_cells(self, data):
        """Render cell-block using given data"""

        cell_styles = ['' for x in self._allcolumns]

        # Style column
        if self.columnstyles:
            for c, s in self.columnstyles:
                cell_styles[self._allcolumns.index(c)] = s

        # Style cells
        if self.cellstyles:
            for c, d, s in self.cellstyles:
                f = bool_formula(d)
                if f(dict(zip(self._allcolumns, data))):
                    cell_styles[self._allcolumns.index(c)] += s

        # formatted columns
        if self.formatters:
            data = list(data)
            for column, formatter in self.formatters.iteritems():
                if data[column] != '': 
                    data[column] = formatter(data[column])

        # Return block of rendered cells (use renderer.cell for actual 
        #   rendering)
        return ''.join(self.renderer.cell(self, cell_styles[k], data[k], i) 
                for i, k in enumerate(self._displaycolumns))
Exemplo n.º 2
0
    def render(self, renderer):
        """Compile data into requested tabular form (via renderer).
        
        Params:
            renderer: object/module used to render data into requested form
        
        Example:
        >>> import datagrid.renderer.ascii
        >>> d = DataGrid([[1,2,3],[4,5,6]], ['col-a', 'col-b', 'col-c'])
        >>> renderer = datagrid.renderer.ascii.Renderer()
        >>> type(d.render(renderer))
        <type 'str'>
        >>> d = DataGrid([[1,2,3],[4,5,6]])
        >>> type(d.render(renderer))
        <type 'str'>
        """
        # make sure we have something to render
        if not len(self.data):
            raise NothingToRenderError()

        # prepare for render
        self._normalize()

        # Filter data
        data = (dict(zip(self._rawcolumns, x)) for x in self.data)
        if self.filters:
            for d in self.filters:
                f = bool_formula(d)
                data = ifilter(f, data)
            self.data = []
            for r in data:
                row = []
                for c in self._rawcolumns:
                    row.append(r[c])
                self.data.append(row)

        # run renderer setup logic (if we have any)
        self.renderer = renderer
        if hasattr(self.renderer, 'setup'): 
            self.renderer.setup(self)

        # build table pieces and glue together
        head = self.renderer.head(self)

        # render body if we are suppressing detail on a flat set
        if not self.suppressdetail or self.groupby:
            body = self._render_body(self.data, self.groupby)
        else:
            body = ''

        taildata = self._add_calculated_columns(
                self._compile_aggregate_data(self.data))
        tail = self.renderer.tail(self, self._render_cells(taildata))

        # render table and return
        return self.renderer.table(self, head, body, tail)
Exemplo n.º 3
0
    def _render_row(self, data, **kargs):
        """Render table-row"""
        row_styles = []

        # Style rows
        if self.rowstyles:
            for d, s in self.rowstyles:
                f = bool_formula(d)
                if f(dict(zip(self._allcolumns, data))):
                    row_styles.append(s)

        return self.renderer.row(self, ' '.join(row_styles), self._render_cells(data), **kargs)
Exemplo n.º 4
0
 def fun(row):
     formatted_row = dict(zip(self._rawcolumns, row))
     for f in self.post_aggregate_filters:
         if not bool_formula(f)(formatted_row):
             return False
     return True
Exemplo n.º 5
0
    def _render_body(self, data, groupby=list(), aggregate_row=None):
        """Render table body segment

        For flat data sets (unaggregated), this includes the entire body of
        data.  Aggregated sets, however, will call _render_body for each 
        aggregation name/value pair."""
        groupby_len = len(groupby)

        if groupby_len:
            # get unique values for aggregation requested
            idx = self._allcolumns.index(groupby[0])

            # create method to group by
            keyfunc = lambda x: x[idx]

            # group data into chunks of aggregated data
            output = []
            data = sorted(data, key=keyfunc)
            for value, subdata in itertools.groupby(data, keyfunc):
               
                # we will be looking at this more than once, so we need a 
                #   concrete list (tuple), not just an iterator
                subdata = tuple(subdata)

                # format aggregate value
                if idx in self.formatters:
                    fvalue = self.formatters[idx](value)
                else:
                    fvalue = value

                # this config gets sent to renderer.row for displaying 
                #   aggregate row information (name, value, etc)
                rowargs = dict(name=groupby[0], value=fvalue, level=groupby_len)
               
                # build aggregate summary row
                rowdata = self._compile_aggregate_data(subdata, aggregate_row)
                rowdata[idx] = value

                # add calculated columns to data
                rowdata = self._add_calculated_columns(rowdata)

                # if details are suppressed, decrement out agg-level
                if self.suppressdetail: 
                    rowargs['level'] -= 1

                # Do post aggregate filters
                def fun(row):
                    formatted_row = dict(zip(self._rawcolumns, row))
                    for f in self.post_aggregate_filters:
                        if not bool_formula(f)(formatted_row):
                            return False
                    return True

                if any(map(fun, subdata)):
                    # generate aggregate row
                    rowoutput = self._render_row(rowdata, **rowargs)

                    # render remainder of rows beneath aggregation level
                    if rowargs['level'] > 0:
                        rowoutput += self._render_body(subdata, groupby[1:], 
                                rowdata)

                    # append rendered data to output buffer
                    output.append((rowdata, rowoutput))

            # sort aggregate row sorting and return compiled string
            output = multi_sorted(output, self.sortby, lambda c, d: d[0][c])
            return ''.join(row[1] for row in output)
        else:
            # Find calculated column values and apply formatting for given row
            data = [self._add_calculated_columns(row) for row in data]

            if self.post_aggregate_filters:
                for f in self.post_aggregate_filters:
                    data = [r for r in data if bool_formula(f)(
                        dict(zip(self._allcolumns, r)))]

            # sort data and display
            data = multi_sorted(data, self.sortby)
            return ''.join(self._render_row(row) for row in data)