def handle(self, *args, **kwargs): try: service = AnalyticsService() except AnalyticsError as e: raise CommandError("Could not connect to analytics service: {0}".format(e), e) yesterday = date_yesterday() print "Downloading click counts from GA..." try: clicks = service.get_clicks_for_date(yesterday) except AnalyticsError as e: raise CommandError("Could not retrieve click data from analytics service: {0}".format(e)) print "Adding datapoints to database..." datapoints = [] for pk in Link.objects.values_list("id", flat=True): datapoint = DataPoint(link_id=pk, date=yesterday, link_clicks=clicks.get(unicode(pk), 0)) datapoints.append(datapoint) try: DataPoint.objects.bulk_create(datapoints, batch_size=1000) except IntegrityError as e: raise CommandError("Could not insert datapoints into database due to IntegrityError.", e) print "Done!"
def setUp(self): # Avoid connecting to real API during tests. self.build_service = self.create_patch( 'affiliates.links.google_analytics.build_service') with self._mock_open(): self.service = AnalyticsService('keyfile.p12', '*****@*****.**', 125)
def test_init_oauth2error(self): """ If there is an error authenticating via oauth, raise AnalyticsError. """ with self._mock_open(read_data='asdf'): self.build_service.side_effect = OAuth2Error with self.assertRaises(AnalyticsError): AnalyticsService('keyfile.p12', '*****@*****.**', 125)
def handle_quiet(self, query_date=None, *args, **kwargs): try: service = AnalyticsService() except AnalyticsError as e: raise CommandError( 'Could not connect to analytics service: {0}'.format(e), e) if query_date == 'today': query_date = timezone.now().date() elif query_date: try: unaware_query_datetime = datetime.strptime( query_date, '%d-%m-%Y') except ValueError: raise CommandError( 'Date argument invalid. It must be in DD-MM-YYYY format') query_date = timezone.make_aware(unaware_query_datetime, timezone.utc).date() else: query_date = timezone.now() - timedelta(days=2) self.output('Downloading click counts from GA...') try: clicks = service.get_clicks_for_date(query_date) except AnalyticsError as e: raise CommandError( 'Could not retrieve click data from analytics service: {0}'. format(e)) self.output('Adding datapoints to database...') datapoints = [] for pk in Link.objects.values_list('id', flat=True): datapoint = DataPoint(link_id=pk, date=query_date, link_clicks=clicks.get(unicode(pk), 0)) datapoints.append(datapoint) # Remove existing data, because supposedly our data is more # up-to-date. DataPoint.objects.filter(date=query_date).delete() DataPoint.objects.bulk_create(datapoints) self.output('Done!')
def handle_quiet(self, query_date=None, *args, **kwargs): try: service = AnalyticsService() except AnalyticsError as e: raise CommandError('Could not connect to analytics service: {0}'.format(e), e) if query_date == 'today': query_date = timezone.now().date() elif query_date: try: unaware_query_datetime = datetime.strptime(query_date, '%d-%m-%Y') except ValueError: raise CommandError('Date argument invalid. It must be in DD-MM-YYYY format') query_date = timezone.make_aware(unaware_query_datetime, timezone.utc).date() else: query_date = timezone.now() - timedelta(days=2) self.output('Downloading click counts from GA...') try: clicks = service.get_clicks_for_date(query_date) except AnalyticsError as e: raise CommandError('Could not retrieve click data from analytics service: {0}' .format(e)) self.output('Adding datapoints to database...') datapoints = [] for pk in Link.objects.values_list('id', flat=True): datapoint = DataPoint(link_id=pk, date=query_date, link_clicks=clicks.get(unicode(pk), 0)) datapoints.append(datapoint) # Remove existing data, because supposedly our data is more # up-to-date. DataPoint.objects.filter(date=query_date).delete() DataPoint.objects.bulk_create(datapoints) self.output('Done!')
def test_init_defaults(self): with self._mock_open(read_data='asdf') as _open: SignedJwtAssertionCredentials = self.create_patch( 'affiliates.links.google_analytics.SignedJwtAssertionCredentials' ) with self.settings(GA_API_PROFILE_ID=125, GA_API_KEYFILE='keyfile.p12', GA_API_ACCOUNT_EMAIL='*****@*****.**'): service = AnalyticsService() _open.assert_called_with('keyfile.p12', ANY) SignedJwtAssertionCredentials.assert_called_with( '*****@*****.**', ANY, scope=ANY) eq_(service.profile_id, 125)
def test_init(self): with self._mock_open(read_data='asdf') as _open: SignedJwtAssertionCredentials = self.create_patch( 'affiliates.links.google_analytics.SignedJwtAssertionCredentials' ) credentials = SignedJwtAssertionCredentials.return_value http = credentials.authorize.return_value service = AnalyticsService('keyfile.p12', '*****@*****.**', 125) _open.assert_called_with('keyfile.p12', 'rb') SignedJwtAssertionCredentials.assert_called_with( '*****@*****.**', 'asdf', scope='https://www.googleapis.com/auth/analytics.readonly') self.build_service.assert_called_with('analytics', 'v3', http=http) eq_(service._service, self.build_service.return_value) eq_(service.profile_id, 125)
def setUp(self): # Avoid connecting to real API during tests. self.build_service = self.create_patch("affiliates.links.google_analytics.build_service") with self._mock_open(): self.service = AnalyticsService("keyfile.p12", "*****@*****.**", 125)
class AnalyticsServiceTests(TestCase): def setUp(self): # Avoid connecting to real API during tests. self.build_service = self.create_patch("affiliates.links.google_analytics.build_service") with self._mock_open(): self.service = AnalyticsService("keyfile.p12", "*****@*****.**", 125) def _mock_open(self, *args, **kwargs): m = mock_open(*args, **kwargs) return patch("affiliates.links.google_analytics.open", m, create=True) def test_init_keyfile_missing(self): """If the keyfile can't be found, raise AnalyticsError.""" with self._mock_open() as _open: _open.side_effect = IOError with self.assertRaises(AnalyticsError): AnalyticsService("keyfile.p12", "*****@*****.**", 125) def test_init_oauth2error(self): """ If there is an error authenticating via oauth, raise AnalyticsError. """ with self._mock_open(read_data="asdf"): self.build_service.side_effect = OAuth2Error with self.assertRaises(AnalyticsError): AnalyticsService("keyfile.p12", "*****@*****.**", 125) def test_init(self): with self._mock_open(read_data="asdf") as _open: SignedJwtAssertionCredentials = self.create_patch( "affiliates.links.google_analytics.SignedJwtAssertionCredentials" ) credentials = SignedJwtAssertionCredentials.return_value http = credentials.authorize.return_value service = AnalyticsService("keyfile.p12", "*****@*****.**", 125) _open.assert_called_with("keyfile.p12", "rb") SignedJwtAssertionCredentials.assert_called_with( "*****@*****.**", "asdf", scope="https://www.googleapis.com/auth/analytics.readonly" ) self.build_service.assert_called_with("analytics", "v3", http=http) eq_(service._service, self.build_service.return_value) eq_(service.profile_id, 125) def test_init_defaults(self): with self._mock_open(read_data="asdf") as _open: SignedJwtAssertionCredentials = self.create_patch( "affiliates.links.google_analytics.SignedJwtAssertionCredentials" ) with self.settings( GA_API_PROFILE_ID=125, GA_API_KEYFILE="keyfile.p12", GA_API_ACCOUNT_EMAIL="*****@*****.**" ): service = AnalyticsService() _open.assert_called_with("keyfile.p12", ANY) SignedJwtAssertionCredentials.assert_called_with("*****@*****.**", ANY, scope=ANY) eq_(service.profile_id, 125) def test_get_data_http_error(self): """ If an HttpError is rasied during _get_data, raise AnalyticsError. """ query = self.service._service.data.return_value.ga.return_value.get.return_value # Mock HttpError because it requires some extra junk to # initialize that is annoying to provide. with patch("affiliates.links.google_analytics.HttpError", Exception) as HttpError: query.execute.side_effect = HttpError with self.assertRaises(AnalyticsError): self.service._get_data() def test_get_data(self): mock_get = self.service._service.data.return_value.ga.return_value.get eq_(self.service._get_data(foo="bar", baz=1), mock_get.return_value.execute.return_value) mock_get.assert_called_with(ids="ga:125", foo="bar", baz=1) def test_get_clicks_for_date_sampled_data(self): """ If settings.DEBUG is false and the result has sampled data, raise AnalyticsError. """ self.service._get_data = Mock(return_value={"containsSampledData": True}) with self.assertRaises(AnalyticsError): self.service.get_clicks_for_date(date(2014, 1, 1)) def test_get_clicks_for_date_sampled_data_default(self): """ If the result doesn't say if it has sampled data or not, assume that it doesn't. """ self.service._get_data = Mock(return_value={}) eq_(self.service.get_clicks_for_date(date(2014, 1, 1)), {}) def test_get_clicks_for_date_no_rows(self): """ If no rows are returned from the API, return an empty dict. """ self.service._get_data = Mock(return_value={"containsSampledData": False}) eq_(self.service.get_clicks_for_date(date(2014, 1, 1)), {}) def test_get_clicks_for_date(self): self.service._get_data = Mock(return_value={"containsSampledData": False, "rows": [["5", "4"], ["3", "2"]]}) eq_(self.service.get_clicks_for_date(date(2014, 1, 1)), {"5": "4", "3": "2"}) self.service._get_data.assert_called_with( start_date="2014-01-01", end_date="2014-01-01", metrics="ga:pageviews", dimensions="ga:customVarValue1" )
def test_init_keyfile_missing(self): """If the keyfile can't be found, raise AnalyticsError.""" with self._mock_open() as _open: _open.side_effect = IOError with self.assertRaises(AnalyticsError): AnalyticsService('keyfile.p12', '*****@*****.**', 125)
class AnalyticsServiceTests(TestCase): def setUp(self): # Avoid connecting to real API during tests. self.build_service = self.create_patch( 'affiliates.links.google_analytics.build_service') with self._mock_open(): self.service = AnalyticsService('keyfile.p12', '*****@*****.**', 125) def _mock_open(self, *args, **kwargs): m = mock_open(*args, **kwargs) return patch('affiliates.links.google_analytics.open', m, create=True) def test_init_keyfile_missing(self): """If the keyfile can't be found, raise AnalyticsError.""" with self._mock_open() as _open: _open.side_effect = IOError with self.assertRaises(AnalyticsError): AnalyticsService('keyfile.p12', '*****@*****.**', 125) def test_init_oauth2error(self): """ If there is an error authenticating via oauth, raise AnalyticsError. """ with self._mock_open(read_data='asdf'): self.build_service.side_effect = OAuth2Error with self.assertRaises(AnalyticsError): AnalyticsService('keyfile.p12', '*****@*****.**', 125) def test_init(self): with self._mock_open(read_data='asdf') as _open: SignedJwtAssertionCredentials = self.create_patch( 'affiliates.links.google_analytics.SignedJwtAssertionCredentials' ) credentials = SignedJwtAssertionCredentials.return_value http = credentials.authorize.return_value service = AnalyticsService('keyfile.p12', '*****@*****.**', 125) _open.assert_called_with('keyfile.p12', 'rb') SignedJwtAssertionCredentials.assert_called_with( '*****@*****.**', 'asdf', scope='https://www.googleapis.com/auth/analytics.readonly') self.build_service.assert_called_with('analytics', 'v3', http=http) eq_(service._service, self.build_service.return_value) eq_(service.profile_id, 125) def test_init_defaults(self): with self._mock_open(read_data='asdf') as _open: SignedJwtAssertionCredentials = self.create_patch( 'affiliates.links.google_analytics.SignedJwtAssertionCredentials' ) with self.settings(GA_API_PROFILE_ID=125, GA_API_KEYFILE='keyfile.p12', GA_API_ACCOUNT_EMAIL='*****@*****.**'): service = AnalyticsService() _open.assert_called_with('keyfile.p12', ANY) SignedJwtAssertionCredentials.assert_called_with( '*****@*****.**', ANY, scope=ANY) eq_(service.profile_id, 125) def test_get_data_http_error(self): """ If an HttpError is rasied during _get_data, raise AnalyticsError. """ query = self.service._service.data.return_value.ga.return_value.get.return_value # Mock HttpError because it requires some extra junk to # initialize that is annoying to provide. with patch('affiliates.links.google_analytics.HttpError', Exception) as HttpError: query.execute.side_effect = HttpError with self.assertRaises(AnalyticsError): self.service._get_data() def test_get_data(self): mock_get = self.service._service.data.return_value.ga.return_value.get eq_(self.service._get_data(foo='bar', baz=1), mock_get.return_value.execute.return_value) mock_get.assert_called_with(ids='ga:125', foo='bar', baz=1) def test_get_clicks_for_date_sampled_data(self): """ If settings.DEBUG is false and the result has sampled data, raise AnalyticsError. """ self.service._get_data = Mock( return_value={'containsSampledData': True}) with self.assertRaises(AnalyticsError): self.service.get_clicks_for_date(date(2014, 1, 1)) def test_get_clicks_for_date_sampled_data_default(self): """ If the result doesn't say if it has sampled data or not, assume that it doesn't. """ self.service._get_data = Mock(return_value={}) eq_(self.service.get_clicks_for_date(date(2014, 1, 1)), {}) def test_get_clicks_for_date_no_rows(self): """ If no rows are returned from the API, return an empty dict. """ self.service._get_data = Mock( return_value={'containsSampledData': False}) eq_(self.service.get_clicks_for_date(date(2014, 1, 1)), {}) def test_get_clicks_for_date(self): self.service._get_data = Mock(return_value={ 'containsSampledData': False, 'rows': [['5', '4'], ['3', '2']] }) eq_(self.service.get_clicks_for_date(date(2014, 1, 1)), { '5': '4', '3': '2' }) self.service._get_data.assert_called_with( start_date='2014-01-01', end_date='2014-01-01', metrics='ga:pageviews', dimensions='ga:customVarValue1')