Example #1
0
def aggregate(dataset, measures=['amount'], drilldowns=None, cuts=None,
              page=1, pagesize=10000, order=None, inflate=None):
    """
    Do an aggregation over a single dataset. This method calls the aggregation
    method of the dataset but in case inflation is asked for, this method takes
    care of those computations
    """

    # If we have to inflate we need to add a year to the drilldowns 
    # (since inflation only supports years at the moment).
    if inflate:
        drilldowns.append('time.year')

    # Aggregate the dataset via its own aggregate function
    result = dataset.aggregate(measures=measures, drilldowns=drilldowns,
                               cuts=cuts, page=page,pagesize=pagesize,
                               order=order)

    # If we have to inflate we do some inflation calculations
    if inflate:
        try:
            # Since different parts of the drilldowns are going to change
            # (differently) we need to recompute the sumamry total
            summary_total = 0
        
            # We collect adjusted drilldowns into a new dict since if
            # inflation fails we can still serve the uninflated content
            adjusted_drilldowns = {}
            # We remove the time.year we added to the drilldowns
            hash_key = drilldowns[:]
            hash_key.remove('time.year')

            for item in result['drilldown']:
                # Get the inflated amount for this year (returns an inflation
                # dictionary with values for reference and target dates along
                # with original and inflated amounts)
                adjustment = helpers.inflate(item['amount'],
                                             inflate, item['time'],
                                             dataset.territories)

                # We make the reference and target datestrings with ISO format
                # (ISO format is yyyy-mm-dd).
                adjustment['reference'] = adjustment['reference'].isoformat()
                adjustment['target'] = adjustment['target'].isoformat()

                # Get the inflated amount into its own variable
                inflated_amount = adjustment['inflated']

                # Get the item key
                item_key = unicode([get_value(k, item) for k in hash_key])
                if item_key not in adjusted_drilldowns:
                    # We copy the item in case something happens (then we
                    # catch it and serve the original aggregation result)
                    adjusted_drilldown = item.copy()
                    remove_excessive_time(hash_key, adjusted_drilldown)
                    adjusted_drilldown['inflation_adjustment'] = [adjustment]
                    adjusted_drilldown['amount'] = inflated_amount
                    adjusted_drilldowns[item_key] = adjusted_drilldown
                else:
                    adjusted_drilldowns[item_key]['inflation_adjustment']\
                        .append(adjustment)
                    adjusted_drilldowns[item_key]['amount'] += inflated_amount

                summary_total += inflated_amount
            
            result['drilldown'] = adjusted_drilldowns.values()
            result['summary']['original'] = result['summary']['amount']
            result['summary']['amount'] = summary_total
        except KeyError, error:
            # If inflation fails because a date wasn't found in the inflation
            # data, then it raises a KeyError (returning the date in the
            # exception message

            # Note we do not remove time.year from the drilldown here since
            # it can help resolve the warning (and it's bothersome)
            result['warning'] = {'inflation':
                                     'Unable to do inflation adjustment',
                                 'error': 'Inflation error: %s' % error}
Example #2
0
    def view(self, dataset, id, format='html'):
        """
        Get a specific entry in the dataset, identified by the id. Entry
        can be return as html (default), json or csv.
        """

        # Generate the dataset
        self._get_dataset(dataset)
        # Get the entry that matches the given id. c.dataset.entries is
        # a generator so we create a list from it's responses based on the
        # given constraint
        entries = list(c.dataset.entries(c.dataset.alias.c.id == id))
        # Since we're trying to get a single entry the list should only
        # contain one entry, if not then we return an error
        if not len(entries) == 1:
            abort(404, _('Sorry, there is no entry %r') % id)
        # Add urls to the dataset and assign assign it as a context variable
        c.entry = entry_apply_links(dataset, entries.pop())

        # Get and set some context variables from the entry
        # This shouldn't really be necessary but it's here so nothing gets
        # broken
        c.id = c.entry.get('id')
        c.from_ = c.entry.get('from')
        c.to = c.entry.get('to')
        c.currency = c.entry.get('currency', c.dataset.currency).upper()
        c.time = c.entry.get('time')

        # Get the amount for the entry
        amount = c.entry.get('amount')
        # We adjust for inflation if the user as asked for this to be inflated
        if 'inflate' in request.params:
            try:
                # Inflate the amount. Target date is provided in request.params
                # as value for inflate and reference date is the date of the
                # entry. We also provide a list of the territories to extract
                # a single country for which to do the inflation
                c.inflation = h.inflate(amount, request.params['inflate'],
                                        c.time, c.dataset.territories)

                # The amount to show should be the inflated amount
                # and overwrite the entry's amount as well
                c.amount = c.inflation['inflated']
                c.entry['amount'] = c.inflation['inflated']

                # We include the inflation response in the entry's dict
                # HTML description assumes every dict value for the entry
                # includes a label so we include a default "Inflation
                # adjustment" for it to work.
                c.inflation['label'] = 'Inflation adjustment'
                c.entry['inflation_adjustment'] = c.inflation
            except:
                # If anything goes wrong in the try clause (and there's a lot
                # that can go wrong). We just say that we can't adjust for
                # inflation and set the context amount as the original amount
                h.flash_notice(_('Unable to adjust for inflation'))
                c.amount = amount
        else:
            # If we haven't been asked to inflate then we just use the
            # original amount
            c.amount = amount

        # Add custom html for the dataset entry if the dataset has some
        # custom html
        # 2013-11-17 disabled this as part of removal of genshi as depended on
        # a genshi specific helper.
        # TODO: reinstate if important
        # c.custom_html = h.render_entry_custom_html(c.dataset, c.entry)

        # Add the rest of the dimensions relating to this entry into a
        # extras dictionary. We first need to exclude all dimensions that
        # are already shown and then we can loop through the dimensions
        excluded_keys = ('time', 'amount', 'currency', 'from', 'to', 'dataset',
                         'id', 'name', 'description')

        c.extras = {}
        if c.dataset:
            # Create a dictionary of the dataset dimensions
            c.desc = dict([(d.name, d) for d in c.dataset.dimensions])
            # Loop through dimensions of the entry
            for key in c.entry:
                # Entry dimension must be a dataset dimension and not in
                # the predefined excluded keys
                if key in c.desc and \
                        key not in excluded_keys:
                    c.extras[key] = c.entry[key]

        # Return entry based on
        if format == 'json':
            return to_jsonp(c.entry)
        elif format == 'csv':
            return write_csv([c.entry], response)
        else:
            return templating.render('entry/view.html')
Example #3
0
    def view(self, dataset, id, format='html'):
        """
        Get a specific entry in the dataset, identified by the id. Entry
        can be return as html (default), json or csv.
        """

        # Generate the dataset
        self._get_dataset(dataset)
        # Get the entry that matches the given id. c.dataset.entries is 
        # a generator so we create a list from it's responses based on the
        # given constraint
        entries = list(c.dataset.entries(c.dataset.alias.c.id == id))
        # Since we're trying to get a single entry the list should only 
        # contain one entry, if not then we return an error
        if not len(entries) == 1:
            abort(404, _('Sorry, there is no entry %r') % id)
        # Add urls to the dataset and assign assign it as a context variable
        c.entry = entry_apply_links(dataset, entries.pop())

        # Get and set some context variables from the entry
        # This shouldn't really be necessary but it's here so nothing gets
        # broken
        c.id = c.entry.get('id')
        c.from_ = c.entry.get('from')
        c.to = c.entry.get('to')
        c.currency = c.entry.get('currency', c.dataset.currency).upper()
        c.time = c.entry.get('time')

        # Get the amount for the entry
        amount = c.entry.get('amount')
        # We adjust for inflation if the user as asked for this to be inflated
        if request.params.has_key('inflate'):
            try:
                # Inflate the amount. Target date is provided in request.params
                # as value for inflate and reference date is the date of the
                # entry. We also provide a list of the territories to extract
                # a single country for which to do the inflation
                c.inflation = h.inflate(amount, request.params['inflate'],
                                        c.time, c.dataset.territories)

                # The amount to show should be the inflated amount
                # and overwrite the entry's amount as well
                c.amount = c.inflation['inflated']
                c.entry['amount'] = c.inflation['inflated']

                # We include the inflation response in the entry's dict
                # HTML description assumes every dict value for the entry
                # includes a label so we include a default "Inflation
                # adjustment" for it to work.
                c.inflation['label'] = 'Inflation adjustment'
                c.entry['inflation_adjustment'] = c.inflation
            except:
                # If anything goes wrong in the try clause (and there's a lot
                # that can go wrong). We just say that we can't adjust for
                # inflation and set the context amount as the original amount
                h.flash_notice(_('Unable to adjust for inflation'))
                c.amount = amount
        else:
            # If we haven't been asked to inflate then we just use the
            # original amount
            c.amount = amount

        # Add custom html for the dataset entry if the dataset has some
        # custom html
        # 2013-11-17 disabled this as part of removal of genshi as depended on
        # a genshi specific helper.
        # TODO: reinstate if important
        # c.custom_html = h.render_entry_custom_html(c.dataset, c.entry)

        # Add the rest of the dimensions relating to this entry into a
        # extras dictionary. We first need to exclude all dimensions that
        # are already shown and then we can loop through the dimensions
        excluded_keys = ('time', 'amount', 'currency', 'from',
                         'to', 'dataset', 'id', 'name', 'description')

        c.extras = {}
        if c.dataset:
            # Create a dictionary of the dataset dimensions
            c.desc = dict([(d.name, d) for d in c.dataset.dimensions])
            # Loop through dimensions of the entry
            for key in c.entry:
                # Entry dimension must be a dataset dimension and not in
                # the predefined excluded keys
                if key in c.desc and \
                        not key in excluded_keys:
                    c.extras[key] = c.entry[key]

        # Return entry based on 
        if format == 'json':
            return to_jsonp(c.entry)
        elif format == 'csv':
            return write_csv([c.entry], response)
        else:
            return templating.render('entry/view.html')
Example #4
0
def aggregate(dataset,
              measures=['amount'],
              drilldowns=None,
              cuts=None,
              page=1,
              pagesize=10000,
              order=None,
              inflate=None):
    """
    Do an aggregation over a single dataset. This method calls the aggregation
    method of the dataset but in case inflation is asked for, this method takes
    care of those computations
    """

    # If we have to inflate we need to add a year to the drilldowns
    # (since inflation only supports years at the moment).
    if inflate:
        drilldowns.append('time.year')

    # Aggregate the dataset via its own aggregate function
    result = dataset.aggregate(measures=measures,
                               drilldowns=drilldowns,
                               cuts=cuts,
                               page=page,
                               pagesize=pagesize,
                               order=order)

    # If we have to inflate we do some inflation calculations
    if inflate:
        try:
            # Since different parts of the drilldowns are going to change
            # (differently) we need to recompute the sumamry total
            summary_total = 0

            # We collect adjusted drilldowns into a new dict since if
            # inflation fails we can still serve the uninflated content
            adjusted_drilldowns = {}
            # We remove the time.year we added to the drilldowns
            hash_key = drilldowns[:]
            hash_key.remove('time.year')

            for item in result['drilldown']:
                # Get the inflated amount for this year (returns an inflation
                # dictionary with values for reference and target dates along
                # with original and inflated amounts)
                adjustment = helpers.inflate(item['amount'], inflate,
                                             item['time'], dataset.territories)

                # We make the reference and target datestrings with ISO format
                # (ISO format is yyyy-mm-dd).
                adjustment['reference'] = adjustment['reference'].isoformat()
                adjustment['target'] = adjustment['target'].isoformat()

                # Get the inflated amount into its own variable
                inflated_amount = adjustment['inflated']

                # Get the item key
                item_key = unicode([get_value(k, item) for k in hash_key])
                if item_key not in adjusted_drilldowns:
                    # We copy the item in case something happens (then we
                    # catch it and serve the original aggregation result)
                    adjusted_drilldown = item.copy()
                    remove_excessive_time(hash_key, adjusted_drilldown)
                    adjusted_drilldown['inflation_adjustment'] = [adjustment]
                    adjusted_drilldown['amount'] = inflated_amount
                    adjusted_drilldowns[item_key] = adjusted_drilldown
                else:
                    adjusted_drilldowns[item_key]['inflation_adjustment'] \
                        .append(adjustment)
                    adjusted_drilldowns[item_key]['amount'] += inflated_amount

                summary_total += inflated_amount

            result['drilldown'] = adjusted_drilldowns.values()
            result['summary']['original'] = result['summary']['amount']
            result['summary']['amount'] = summary_total
        except KeyError as error:
            # If inflation fails because a date wasn't found in the inflation
            # data, then it raises a KeyError (returning the date in the
            # exception message

            # Note we do not remove time.year from the drilldown here since
            # it can help resolve the warning (and it's bothersome)
            result['warning'] = {
                'inflation': 'Unable to do inflation adjustment',
                'error': 'Inflation error: %s' % error
            }

    return result