Refactor graph code. Querying to build a Top Packages graph.
Refactor graph code. Querying to build a Top Packages graph.

file:a/.gitignore -> file:b/.gitignore
*.py[co] *.py[co]
  *.py~
  .gitignore
  ckan.log
   
# Packages # Packages
*.egg *.egg
*.egg-info *.egg-info
dist dist
build build
eggs eggs
parts parts
bin bin
var var
sdist sdist
develop-eggs develop-eggs
.installed.cfg .installed.cfg
   
  # Private info
  credentials.json
  token.dat
   
# Installer logs # Installer logs
pip-log.txt pip-log.txt
   
# Unit test / coverage reports # Unit test / coverage reports
.coverage .coverage
.tox .tox
   
#Translations #Translations
*.mo *.mo
   
#Mr Developer #Mr Developer
.mr.developer.cfg .mr.developer.cfg
   
file:a/README.md (deleted)
ckanext-ga-report  
=================  
 
For creating detailed reports of CKAN analytics, sliced by group  
file:b/README.rst (new)
  ckanext-ga-report
  =================
 
  **Status:** Development
 
  **CKAN Version:** 1.7.1+
 
 
  Overview
  --------
 
  For creating detailed reports of CKAN analytics, including totals per group.
 
  Whereas ckanext-googleanalytics focusses on providing page view stats a recent period and for all time (aimed at end users), ckanext-ga-report is more interested in building regular periodic reports (more for site managers to monitor).
 
  Contents of this extension:
 
  * Use the CLI tool to download Google Analytics data for each time period into this extension's database tables
 
  * Users can view the data as web page reports
 
 
  Installation
  ------------
 
  1. Activate you CKAN python environment and install this extension's software::
 
  $ pyenv/bin/activate
  $ pip install -e git+https://github.com/datagovuk/ckanext-ga-report.git#egg=ckanext-ga-report
 
  2. Ensure you development.ini (or similar) contains the info about your Google Analytics account and configuration::
 
  googleanalytics.id = UA-1010101-1
  googleanalytics.account = Account name (e.g. data.gov.uk, see top level item at https://www.google.com/analytics)
  googleanalytics.token.filepath = ~/pyenv/token.dat
  ga-report.period = monthly
  ga-report.bounce_url = /
 
  The ga-report.bounce_url specifies a particular path to record the bounce rate for. Typically it is / (the home page).
 
  3. Set up this extension's database tables using a paster command. (Ensure your CKAN pyenv is still activated, run the command from ``src/ckanext-ga-report``, alter the ``--config`` option to point to your site config file)::
 
  $ paster initdb --config=../ckan/development.ini
 
  4. Enable the extension in your CKAN config file by adding it to ``ckan.plugins``::
 
  ckan.plugins = ga-report
 
  Problem shooting
  ----------------
 
  * ``(ProgrammingError) relation "ga_url" does not exist``
  This means that the ``paster initdb`` step has not been run successfully. Refer to the installation instructions for this extension.
 
 
  Authorization
  --------------
 
  Before you can access the data, you need to set up the OAUTH details which you can do by following the `instructions <https://developers.google.com/analytics/resources/tutorials/hello-analytics-api>`_ the outcome of which will be a file called credentials.json which should look like credentials.json.template with the relevant fields completed. These steps are below for convenience:
 
  1. Visit the `Google APIs Console <https://code.google.com/apis/console>`_
 
  2. Sign-in and create a project or use an existing project.
 
  3. In the `Services pane <https://code.google.com/apis/console#:services>`_ , activate Analytics API for your project. If prompted, read and accept the terms of service.
 
  4. Go to the `API Access pane <https://code.google.com/apis/console/#:access>`_
 
  5. Click Create an OAuth 2.0 client ID....
 
  6. Fill out the Branding Information fields and click Next.
 
  7. In Client ID Settings, set Application type to Installed application.
 
  8. Click Create client ID
 
  9. The details you need below are Client ID, Client secret, and Redirect URIs
 
 
  Once you have set up your credentials.json file you can generate an oauth token file by using the
  following command, which will store your oauth token in a file called token.dat once you have finished
  giving permission in the browser::
 
  $ paster getauthtoken --config=../ckan/development.ini
 
  Now ensure you reference the correct path to your token.dat in your CKAN config file (e.g. development.ini)::
 
  googleanalytics.token.filepath = ~/pyenv/token.dat
 
 
  Tutorial
  --------
 
  Download some GA data and store it in CKAN's database. (Ensure your CKAN pyenv is still activated, run the command from ``src/ckanext-ga-report``, alter the ``--config`` option to point to your site config file) and specifying the name of your auth file (token.dat by default) from the previous step::
 
  $ paster loadanalytics latest --config=../ckan/development.ini
 
  The value after the token file is how much data you want to retrieve, this can be
 
  * **all** - data for all time (since 2010)
 
  * **latest** - (default) just the 'latest' data
 
  * **YYYY-MM-DD** - just data for all time periods going back to (and including) this date
 
 
 
  Software Licence
  ================
 
  This software is developed by Cabinet Office. It is Crown Copyright and opened up under the Open Government Licence (OGL) (which is compatible with Creative Commons Attibution License).
 
  OGL terms: http://www.nationalarchives.gov.uk/doc/open-government-licence/
 
  # this is a namespace package
  try:
  import pkg_resources
  pkg_resources.declare_namespace(__name__)
  except ImportError:
  import pkgutil
  __path__ = pkgutil.extend_path(__path__, __name__)
 
  # this is a namespace package
  try:
  import pkg_resources
  pkg_resources.declare_namespace(__name__)
  except ImportError:
  import pkgutil
  __path__ = pkgutil.extend_path(__path__, __name__)
 
  import logging
  import datetime
  import os
 
  from pylons import config
 
  from ckan.lib.cli import CkanCommand
  # No other CKAN imports allowed until _load_config is run,
  # or logging is disabled
 
 
  class InitDB(CkanCommand):
  """Initialise the extension's database tables
  """
  summary = __doc__.split('\n')[0]
  usage = __doc__
  max_args = 0
  min_args = 0
 
  def command(self):
  self._load_config()
 
  import ckan.model as model
  model.Session.remove()
  model.Session.configure(bind=model.meta.engine)
  log = logging.getLogger('ckanext.ga-report')
 
  import ga_model
  ga_model.init_tables()
  log.info("DB tables are setup")
 
 
  class GetAuthToken(CkanCommand):
  """ Get's the Google auth token
 
  Usage: paster getauthtoken <credentials_file>
 
  Where <credentials_file> is the file name containing the details
  for the service (obtained from https://code.google.com/apis/console).
  By default this is set to credentials.json
  """
  summary = __doc__.split('\n')[0]
  usage = __doc__
  max_args = 0
  min_args = 0
 
  def command(self):
  """
  In this case we don't want a valid service, but rather just to
  force the user through the auth flow. We allow this to complete to
  act as a form of verification instead of just getting the token and
  assuming it is correct.
  """
  from ga_auth import init_service
  init_service('token.dat',
  self.args[0] if self.args
  else 'credentials.json')
 
  class FixTimePeriods(CkanCommand):
  """
  Fixes the 'All' records for GA_Urls
 
  It is possible that older urls that haven't recently been visited
  do not have All records. This command will traverse through those
  records and generate valid All records for them.
  """
  summary = __doc__.split('\n')[0]
  usage = __doc__
  max_args = 0
  min_args = 0
 
  def __init__(self, name):
  super(FixTimePeriods, self).__init__(name)
 
  def command(self):
  import ckan.model as model
  from ga_model import post_update_url_stats
  self._load_config()
  model.Session.remove()
  model.Session.configure(bind=model.meta.engine)
 
  log = logging.getLogger('ckanext.ga_report')
 
  log.info("Updating 'All' records for old URLs")
  post_update_url_stats()
  log.info("Processing complete")
 
 
 
  class LoadAnalytics(CkanCommand):
  """Get data from Google Analytics API and save it
  in the ga_model
 
  Usage: paster loadanalytics <time-period>
 
  Where <time-period> is:
  all - data for all time
  latest - (default) just the 'latest' data
  YYYY-MM - just data for the specific month
  """
  summary = __doc__.split('\n')[0]
  usage = __doc__
  max_args = 1
  min_args = 0
 
  def __init__(self, name):
  super(LoadAnalytics, self).__init__(name)
  self.parser.add_option('-d', '--delete-first',
  action='store_true',
  default=False,
  dest='delete_first',
  help='Delete data for the period first')
  self.parser.add_option('-s', '--skip_url_stats',
  action='store_true',
  default=False,
  dest='skip_url_stats',
  help='Skip the download of URL data - just do site-wide stats')
 
  def command(self):
  self._load_config()
 
  from download_analytics import DownloadAnalytics
  from ga_auth import (init_service, get_profile_id)
 
  ga_token_filepath = os.path.expanduser(config.get('googleanalytics.token.filepath', ''))
  if not ga_token_filepath:
  print 'ERROR: In the CKAN config you need to specify the filepath of the ' \
  'Google Analytics token file under key: googleanalytics.token.filepath'
  return
 
  try:
  svc = init_service(ga_token_filepath, None)
  except TypeError:
  print ('Have you correctly run the getauthtoken task and '
  'specified the correct token file in the CKAN config under '
  '"googleanalytics.token.filepath"?')
  return
 
  downloader = DownloadAnalytics(svc, profile_id=get_profile_id(svc),
  delete_first=self.options.delete_first,
  skip_url_stats=self.options.skip_url_stats)
 
  time_period = self.args[0] if self.args else 'latest'
  if time_period == 'all':
  downloader.all_()
  elif time_period == 'latest':
  downloader.latest()
  else:
  # The month to use
  for_date = datetime.datetime.strptime(time_period, '%Y-%m')
  downloader.specific_month(for_date)
 
  import re
  import csv
  import sys
  import json
  import logging
  import operator
  import collections
  from ckan.lib.base import (BaseController, c, g, render, request, response, abort)
 
  import sqlalchemy
  from sqlalchemy import func, cast, Integer
  import ckan.model as model
  from ga_model import GA_Url, GA_Stat, GA_ReferralStat, GA_Publisher
 
  log = logging.getLogger('ckanext.ga-report')
 
  DOWNLOADS_AVAILABLE_FROM = '2012-12'
 
  def _get_month_name(strdate):
  import calendar
  from time import strptime
  d = strptime(strdate, '%Y-%m')
  return '%s %s' % (calendar.month_name[d.tm_mon], d.tm_year)
 
  def _get_unix_epoch(strdate):
  from time import strptime,mktime
  d = strptime(strdate, '%Y-%m')
  return int(mktime(d))
 
  def _month_details(cls, stat_key=None):
  '''
  Returns a list of all the periods for which we have data, unfortunately
  knows too much about the type of the cls being passed as GA_Url has a
  more complex query
 
  This may need extending if we add a period_name to the stats
  '''
  months = []
  day = None
 
  q = model.Session.query(cls.period_name,cls.period_complete_day)\
  .filter(cls.period_name!='All').distinct(cls.period_name)
  if stat_key:
 <