Removed all traces of Monolith (bug 974854)

This commit is contained in:
Rob Hudson 2014-02-20 15:43:32 -08:00
Родитель 4c595839d6
Коммит 6306be44eb
23 изменённых файлов: 10 добавлений и 729 удалений

Просмотреть файл

@ -63,19 +63,6 @@ def update_global_totals(date=None):
TaskSet(ts).apply_async()
@cronjobs.register
def update_monolith_stats(date=None):
"""Update monolith statistics."""
if date:
date = datetime.datetime.strptime(date, '%Y-%m-%d').date()
today = date or datetime.date.today()
jobs = [{'metric': metric,
'date': today} for metric in tasks._get_monolith_jobs(date)]
ts = [tasks.update_monolith_stats.subtask(kwargs=kw) for kw in jobs]
TaskSet(ts).apply_async()
@cronjobs.register
def update_google_analytics(date=None):
"""

Просмотреть файл

@ -7,14 +7,11 @@ import mock
from nose.tools import eq_
import amo.tests
from addons.models import Addon, AddonUser
from addons.models import Addon
from bandwagon.models import Collection, CollectionAddon
from mkt.constants.regions import REGIONS_CHOICES_SLUG
from reviews.models import Review
from stats import cron, tasks
from stats.models import (AddonCollectionCount, Contribution, DownloadCount,
GlobalStat, ThemeUserCount, UpdateCount)
from users.models import UserProfile
class TestGlobalStats(amo.tests.TestCase):
@ -195,142 +192,3 @@ class TestUpdateDownloads(amo.tests.TestCase):
eq_(CollectionAddon.objects.get(addon_id=3615,
collection_id=80).downloads,
15)
class TestMonolithStats(amo.tests.TestCase):
@mock.patch('stats.tasks.MonolithRecord')
def test_mmo_user_total_count_updates_monolith(self, record):
UserProfile.objects.create(source=amo.LOGIN_SOURCE_MMO_BROWSERID)
metric = 'mmo_user_count_total'
tasks.update_monolith_stats(metric, datetime.date.today())
self.assertTrue(record.objects.create.called)
eq_(record.objects.create.call_args[1]['value'], '{"count": 1}')
def test_app_new(self):
Addon.objects.create(type=amo.ADDON_WEBAPP)
eq_(tasks._get_monolith_jobs()['apps_count_new'][0]['count'](), 1)
def test_app_added_counts(self):
today = datetime.date(2013, 1, 25)
app = Addon.objects.create(type=amo.ADDON_WEBAPP)
app.update(created=today)
package_type = 'packaged' if app.is_packaged else 'hosted'
premium_type = amo.ADDON_PREMIUM_API[app.premium_type]
# Add a region exclusion.
regions = dict(REGIONS_CHOICES_SLUG)
excluded_region = regions['br']
app.addonexcludedregion.create(region=excluded_region.id)
jobs = tasks._get_monolith_jobs(today)
# Check package type counts.
for job in jobs['apps_added_by_package_type']:
r = job['dimensions']['region']
p = job['dimensions']['package_type']
if r != excluded_region.slug and p == package_type:
expected_count = 1
else:
expected_count = 0
count = job['count']()
eq_(count, expected_count,
'Incorrect count for region %s, package type %s. '
'Got %d, expected %d.' % (r, p, count, expected_count))
# Check premium type counts.
for job in jobs['apps_added_by_premium_type']:
r = job['dimensions']['region']
p = job['dimensions']['premium_type']
if r != excluded_region.slug and p == premium_type:
expected_count = 1
else:
expected_count = 0
count = job['count']()
eq_(count, expected_count,
'Incorrect count for region %s, premium type %s. '
'Got %d, expected %d.' % (r, p, count, expected_count))
def test_app_avail_counts(self):
today = datetime.date(2013, 1, 25)
app = Addon.objects.create(type=amo.ADDON_WEBAPP,
status=amo.STATUS_PUBLIC)
# Create a couple more to test the counts.
Addon.objects.create(type=amo.ADDON_WEBAPP, status=amo.STATUS_PENDING)
Addon.objects.create(type=amo.ADDON_WEBAPP, status=amo.STATUS_PUBLIC,
disabled_by_user=True)
package_type = 'packaged' if app.is_packaged else 'hosted'
premium_type = amo.ADDON_PREMIUM_API[app.premium_type]
# Add a region exclusion.
regions = dict(REGIONS_CHOICES_SLUG)
excluded_region = regions['br']
app.addonexcludedregion.create(region=excluded_region.id)
jobs = tasks._get_monolith_jobs(today)
# Check package type counts.
for job in jobs['apps_available_by_package_type']:
r = job['dimensions']['region']
p = job['dimensions']['package_type']
if r != excluded_region.slug and p == package_type:
expected_count = 1
else:
expected_count = 0
count = job['count']()
eq_(count, expected_count,
'Incorrect count for region %s, package type %s. '
'Got %d, expected %d.' % (r, p, count, expected_count))
# Check premium type counts.
for job in jobs['apps_available_by_premium_type']:
r = job['dimensions']['region']
p = job['dimensions']['premium_type']
if r != excluded_region.slug and p == premium_type:
expected_count = 1
else:
expected_count = 0
count = job['count']()
eq_(count, expected_count,
'Incorrect count for region %s, premium type %s. '
'Got %d, expected %d.' % (r, p, count, expected_count))
def test_app_reviews(self):
addon = Addon.objects.create(type=amo.ADDON_WEBAPP)
user = UserProfile.objects.create(username='foo')
Review.objects.create(addon=addon, user=user)
eq_(tasks._get_monolith_jobs()['apps_review_count_new'][0]['count'](),
1)
def test_user_total(self):
day = datetime.date(2009, 1, 1)
p = UserProfile.objects.create(username='foo',
source=amo.LOGIN_SOURCE_MMO_BROWSERID)
p.update(created=day)
eq_(tasks._get_monolith_jobs(day)['mmo_user_count_total'][0]['count'](),
1)
eq_(tasks._get_monolith_jobs()['mmo_user_count_total'][0]['count'](),
1)
eq_(tasks._get_monolith_jobs()['mmo_user_count_new'][0]['count'](), 0)
def test_user_new(self):
UserProfile.objects.create(username='foo',
source=amo.LOGIN_SOURCE_MMO_BROWSERID)
eq_(tasks._get_monolith_jobs()['mmo_user_count_new'][0]['count'](), 1)
def test_dev_total(self):
p1 = UserProfile.objects.create(username='foo',
source=amo.LOGIN_SOURCE_MMO_BROWSERID)
p2 = UserProfile.objects.create(username='bar',
source=amo.LOGIN_SOURCE_MMO_BROWSERID)
a1 = amo.tests.addon_factory()
a2 = amo.tests.app_factory()
AddonUser.objects.create(addon=a1, user=p1)
AddonUser.objects.create(addon=a1, user=p2)
AddonUser.objects.create(addon=a2, user=p1)
eq_(tasks._get_monolith_jobs()['mmo_developer_count_total'][0]['count'](),
1)

Просмотреть файл

@ -3,16 +3,16 @@ from functools import partial
from django import http
from django.conf import settings
from django.db import IntegrityError, transaction
from django.shortcuts import (get_list_or_404, get_object_or_404,
redirect, render)
from django.contrib import auth
from django.contrib.auth.forms import PasswordResetForm
from django.contrib.auth.tokens import default_token_generator
from django.db import IntegrityError, transaction
from django.shortcuts import (get_list_or_404, get_object_or_404, redirect,
render)
from django.template import Context, loader
from django.utils.http import base36_to_int, is_safe_url
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_exempt
from django.utils.http import base36_to_int, is_safe_url
import commonware.log
import waffle
@ -25,6 +25,7 @@ from tower import ugettext as _
import amo
import users.notifications as notifications
from abuse.models import send_abuse_report
from access import acl
from access.middleware import ACLMiddleware
from addons.decorators import addon_view_factory
from addons.models import Addon, Category
@ -35,19 +36,17 @@ from amo.forms import AbuseForm
from amo.helpers import loc
from amo.urlresolvers import get_url_prefix, reverse
from amo.utils import escape_all, log_cef, send_mail
from access import acl
from bandwagon.models import Collection
from browse.views import PersonasFilter
from translations.query import order_by_translation
from users.models import UserNotification
from lib.metrics import record_action
import tasks
from . import forms
from .models import UserProfile
from .signals import logged_out
from . import forms
from .utils import autocreate_username, EmailResetCode, UnsubscribeCode
import tasks
log = commonware.log.getLogger('z.users')
@ -380,8 +379,6 @@ def browserid_authenticate(request, assertion, is_mobile=False,
log_cef('New Account', 5, request, username=username,
signature='AUTHNOTICE',
msg='User created a new account (from Persona)')
if settings.MARKETPLACE:
record_action('new-user', request)
return profile, None

Просмотреть файл

@ -443,11 +443,6 @@ class TestVersion(amo.tests.TestCase):
amo.tests.version_factory(addon=addon)
assert inv_mock.called
def test_app_feature_creation_app(self):
app = Addon.objects.create(type=amo.ADDON_WEBAPP)
ver = Version.objects.create(addon=app)
assert ver.features, 'AppFeatures was not created with version.'
class TestViews(amo.tests.TestCase):
fixtures = ['addons/eula+contrib-addon', 'base/apps']

Просмотреть файл

@ -1,47 +0,0 @@
import threading
from django.conf import settings
import commonware.log
from mkt.monolith import record_stat
log = commonware.log.getLogger('z.metrics')
def record_action(action, request, data=None):
"""Records the given action by sending it to the metrics servers.
Currently this is storing the data internally in the monolith temporary
table.
:param action: the action related to this request.
:param request: the request that triggered this call.
:param data: some optional additional data about this call.
"""
if data is None:
data = {}
data['user-agent'] = request.META.get('HTTP_USER_AGENT')
data['locale'] = request.LANG
data['src'] = request.GET.get('src', '')
record_stat(action, request, **data)
def get_monolith_client():
_locals = threading.local()
if not hasattr(_locals, 'monolith'):
server = getattr(settings, 'MONOLITH_SERVER', None)
index = getattr(settings, 'MONOLITH_INDEX', 'time_*')
if server is None:
raise ValueError('You need to configure MONOLITH_SERVER')
statsd = {'statsd.host': getattr(settings, 'STATSD_HOST', 'localhost'),
'statsd.port': getattr(settings, 'STATSD_PORT', 8125)}
from monolith.client import Client as MonolithClient
_locals.monolith = MonolithClient(server, index, **statsd)
return _locals.monolith

Просмотреть файл

@ -1,18 +0,0 @@
# -*- coding: utf8 -*-
import mock
import amo.tests
from lib.metrics import record_action
class TestMetrics(amo.tests.TestCase):
@mock.patch('lib.metrics.record_stat')
def test_record_action(self, record_stat):
request = mock.Mock()
request.GET = {'src': 'foo'}
request.LANG = 'en'
request.META = {'HTTP_USER_AGENT': 'py'}
record_action('install', request, {})
record_stat.assert_called_with('install', request,
**{'locale': 'en', 'src': 'foo', 'user-agent': 'py'})

Просмотреть файл

@ -1062,8 +1062,7 @@ CELERY_RESULT_BACKEND = 'amqp'
CELERY_IGNORE_RESULT = True
CELERY_SEND_TASK_ERROR_EMAILS = True
CELERYD_HIJACK_ROOT_LOGGER = False
CELERY_IMPORTS = ('lib.video.tasks', 'lib.metrics',
'lib.es.management.commands.reindex')
CELERY_IMPORTS = ('lib.video.tasks', 'lib.es.management.commands.reindex')
# We have separate celeryds for processing devhub & images as fast as possible
# Some notes:
@ -1079,8 +1078,6 @@ CELERY_ROUTES = {
'addons.tasks.save_theme_reupload': {'queue': 'priority'},
'bandwagon.tasks.index_collections': {'queue': 'priority'},
'bandwagon.tasks.unindex_collections': {'queue': 'priority'},
'lib.crypto.packaged.sign': {'queue': 'priority'},
'stats.tasks.update_monolith_stats': {'queue': 'priority'},
'users.tasks.index_users': {'queue': 'priority'},
'users.tasks.unindex_users': {'queue': 'priority'},

Просмотреть файл

@ -1 +0,0 @@
from mkt.monolith.models import record_stat # NOQA

Просмотреть файл

@ -1,9 +0,0 @@
from django import forms
import happyforms
class MonolithForm(happyforms.Form):
key = forms.CharField(required=False)
start = forms.DateField(required=False)
end = forms.DateField(required=False)

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -1,22 +0,0 @@
from optparse import make_option
from django.conf import settings
from django.core.management.base import BaseCommand
from mkt.site.management.commands.add_test_users import create_user
class Command(BaseCommand):
help = """Create an user with access to the monolith API"""
option_list = BaseCommand.option_list + (
make_option(
'--overwrite', action='store_true',
dest='overwrite', default=False,
help='Overwrite the user access token if it already exists'),)
def handle(self, *args, **kw):
create_user('monolith@mozilla.com',
overwrite=kw['overwrite'],
password=settings.MONOLITH_PASSWORD,
group_name='Monolith API')

Просмотреть файл

@ -1,61 +0,0 @@
import datetime
import hashlib
import json
from django.db import models
class MonolithRecord(models.Model):
"""Data stored temporarily for monolith.
It contains a key (e.g. "app.install"), the date of the record, a user (a
string representing a unique user) and a value (which internally is stored
as a JSON object).
"""
key = models.CharField(max_length=255)
recorded = models.DateTimeField()
user_hash = models.CharField(max_length=255, blank=True)
value = models.TextField()
class Meta:
db_table = 'monolith_record'
def get_user_hash(request):
"""Get a hash identifying an user.
It's a hash of session key, ip and user agent
"""
ip = request.META.get('REMOTE_ADDR', '')
ua = request.META.get('User-Agent', '')
session_key = request.session.session_key or ''
return hashlib.sha1('-'.join(map(str, (ip, ua, session_key)))).hexdigest()
def record_stat(key, request, **data):
"""Create a new record in the database with the given values.
:param key:
The type of stats you're sending, e.g. "app.install".
:param request:
The request associated with this call. It will be used to define who
the user is.
:para: data:
The data you want to store. You can pass the data to this function as
named arguments.
"""
if '__recorded' in data:
recorded = data.pop('__recorded')
else:
recorded = datetime.datetime.utcnow()
if not data:
raise ValueError('You should at least define one value')
record = MonolithRecord(key=key, user_hash=get_user_hash(request),
recorded=recorded, value=json.dumps(data))
record.save()
return record

Просмотреть файл

@ -1,147 +0,0 @@
import datetime
import json
import logging
from django.db.models import Avg, Count
from rest_framework import serializers, status
from rest_framework.exceptions import ParseError
from rest_framework.generics import ListAPIView
from rest_framework.response import Response
import amo
from abuse.models import AbuseReport
from reviews.models import Review
from mkt.api.authentication import RestOAuthAuthentication
from mkt.api.authorization import GroupPermission
from mkt.api.base import CORSMixin, MarketplaceView
from .forms import MonolithForm
from .models import MonolithRecord
log = logging.getLogger('z.monolith')
# TODO: Move the stats that can be calculated on the fly from
# apps/stats/tasks.py here.
STATS = {
'apps_ratings': {
'qs': Review.objects
.filter(editorreview=0, addon__type=amo.ADDON_WEBAPP)
.values('addon')
.annotate(count=Count('addon')),
'type': 'slice',
'field_map': {
'count': 'count',
'app-id': 'addon'},
},
'apps_average_rating': {
'qs': Review.objects
.filter(editorreview=0, addon__type=amo.ADDON_WEBAPP)
.values('addon')
.annotate(avg=Avg('rating')),
'type': 'total',
'field_map': {
'count': 'avg',
'app-id': 'addon'},
},
'apps_abuse_reports': {
'qs': AbuseReport.objects
.filter(addon__type=amo.ADDON_WEBAPP)
.values('addon')
.annotate(count=Count('addon')),
'type': 'slice',
'field_map': {
'count': 'count',
'app-id': 'addon'},
}
}
def daterange(start, end):
for n in range((end - start).days):
yield start + datetime.timedelta(n)
class MonolithSerializer(serializers.ModelSerializer):
class Meta:
model = MonolithRecord
fields = ('key', 'recorded', 'user_hash', 'value')
def transform_value(self, obj, value):
if not isinstance(value, basestring):
return value
return json.loads(value)
def _get_query_result(key, start, end):
# To do on-the-fly queries we have to produce results as if they
# were calculated daily, which means we need to iterate over each
# day in the range and perform an aggregation on this date.
data = []
today = datetime.date.today()
stat = STATS[key]
# Choose start and end dates that make sense if none provided.
if not start:
raise ParseError('`start` was not provided')
if not end:
end = today
for day in daterange(start, end):
if stat['type'] == 'total':
# If it's a totalling queryset, we want to filter by the
# end date until the beginning of time to get the total
# objects up until this point in time.
date_filtered = stat['qs'].filter(
created__lt=(day + datetime.timedelta(days=1)))
else:
# Otherwise, we want to filter by both start/end to get
# counts on a specific day.
date_filtered = stat['qs'].filter(
created__gte=day,
created__lt=(day + datetime.timedelta(days=1)))
data.extend([{
'key': key,
'recorded': day,
'user_hash': None,
'value': {'count': d.get(stat['field_map']['count']),
'app-id': d.get(stat['field_map']['app-id'])}}
for d in date_filtered])
return data
class MonolithView(CORSMixin, MarketplaceView, ListAPIView):
cors_allowed_methods = ['get']
permission_classes = [GroupPermission('Monolith', 'API')]
authentication_classes = [RestOAuthAuthentication]
serializer_class = MonolithSerializer
def get_queryset(self):
form = MonolithForm(self.request.QUERY_PARAMS)
if not form.is_valid():
return Response(form.errors, status=status.HTTP_400_BAD_REQUEST)
key = form.cleaned_data['key']
start = form.cleaned_data['start']
end = form.cleaned_data['end']
log.info('[Monolith] Querying key:%s [%s:%s]' % (key, start, end))
if key in STATS:
return _get_query_result(key, start, end)
else:
qs = MonolithRecord.objects.all()
if key:
qs = qs.filter(key=key)
if start is not None:
qs = qs.filter(recorded__gte=start)
if end is not None:
qs = qs.filter(recorded__lt=end)
return qs

Просмотреть файл

@ -1,228 +0,0 @@
import datetime
import json
import uuid
from collections import namedtuple
import mock
from nose.tools import eq_, ok_
from django.core.urlresolvers import reverse
from django.test import client
from amo.tests import TestCase
from mkt.api.tests.test_oauth import RestOAuth
from mkt.site.fixtures import fixture
from .models import MonolithRecord, record_stat
from .resources import daterange
class RequestFactory(client.RequestFactory):
def __init__(self, session_key=None, user_agent=None,
remote_addr=None, anonymous=True, *args, **kwargs):
class User(object):
def is_anonymous(self):
return anonymous
Session = namedtuple('Session', 'session_key')
self.session = Session(session_key or str(uuid.uuid1()))
self.user = User()
self.META = {}
if remote_addr:
self.META['REMOTE_ADDR'] = remote_addr
if user_agent:
self.META['User-Agent'] = user_agent
super(RequestFactory, self).__init__(*args, **kwargs)
def total_seconds(td):
# not present in 2.6
return ((td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6) /
10 ** 6)
class TestModels(TestCase):
def setUp(self):
super(TestModels, self).setUp()
self.request = RequestFactory()
def test_record_stat(self):
now = datetime.datetime.utcnow()
record_stat('app.install', self.request, value=1)
# we should have only one record
record = MonolithRecord.objects.get()
eq_(record.key, 'app.install')
eq_(record.value, json.dumps({'value': 1}))
self.assertTrue(total_seconds(record.recorded - now) < 1)
def test_record_stat_without_data(self):
with self.assertRaises(ValueError):
record_stat('app.install', self.request)
class TestMonolithResource(RestOAuth):
fixtures = fixture('user_2519')
def setUp(self):
super(TestMonolithResource, self).setUp()
self.grant_permission(self.profile, 'Monolith:API')
self.list_url = reverse('monolith-list')
self.now = datetime.datetime(2013, 02, 12, 17, 34)
self.last_month = self.now - datetime.timedelta(days=30)
self.last_week = self.now - datetime.timedelta(days=7)
self.yesterday = self.now - datetime.timedelta(days=1)
self.date_format = '%Y-%m-%d'
self.request = RequestFactory()
def test_normal_call_with_no_records(self):
res = self.client.get(self.list_url)
eq_(res.status_code, 200)
data = json.loads(res.content)
eq_(data['objects'], [])
def test_normal_call(self):
record_stat('app.install', self.request, value=2)
res = self.client.get(self.list_url)
eq_(res.status_code, 200)
data = json.loads(res.content)
eq_(len(data['objects']), 1)
obj = data['objects'][0]
eq_(obj['key'], 'app.install')
eq_(obj['value'], {'value': 2})
# Check other fields we want to exist but ignore their value here.
for field in ('recorded', 'user_hash'):
assert field in obj
def test_filter_by_date(self):
for id_, date in enumerate((self.last_week, self.yesterday, self.now)):
record_stat('app.install', self.request, __recorded=date,
value=id_)
res = self.client.get(self.list_url, data={
'end': self.now.strftime(self.date_format)})
eq_(res.status_code, 200)
data = json.loads(res.content)
eq_(len(data['objects']), 2)
res = self.client.get(self.list_url, data={
'start': self.yesterday.strftime(self.date_format),
'end': self.now.strftime(self.date_format)})
data = json.loads(res.content)
eq_(len(data['objects']), 1)
def test_filter_by_key(self):
record_stat('apps_added_us_free', self.request, value=3)
record_stat('apps_added_uk_free', self.request, value=1)
# Exact match.
res = self.client.get(self.list_url,
data={'key': 'apps_added_us_free'})
eq_(res.status_code, 200)
data = json.loads(res.content)
eq_(len(data['objects']), 1)
@mock.patch('mkt.monolith.resources._get_query_result')
def test_on_the_fly_query(self, _get_query):
key = 'apps_ratings'
_get_query.return_value = [{
'key': key,
'recorded': datetime.date.today(),
'user_hash': None,
'value': {'count': 1, 'app-id': 123}}]
res = self.client.get(self.list_url, data={'key': key})
eq_(res.status_code, 200)
data = json.loads(res.content)
eq_(len(data['objects']), 1)
obj = data['objects'][0]
eq_(obj['key'], key)
eq_(obj['recorded'], datetime.date.today().strftime(self.date_format))
eq_(obj['value']['count'], 1)
eq_(obj['value']['app-id'], 123)
def test_on_the_fly_missing_start(self):
key = 'apps_ratings'
res = self.client.get(self.list_url, data={'key': key})
eq_(res.status_code, 400)
data = json.loads(res.content)
eq_(data['detail'], '`start` was not provided')
@mock.patch('mkt.monolith.resources._get_query_result')
def test_on_the_fly_query_pagination(self, _get_query):
key = 'apps_ratings'
_get_query.return_value = [
{'key': key, 'recorded': datetime.date.today(), 'user_hash': None,
'value': {'count': 1, 'app-id': 123}},
{'key': key, 'recorded': datetime.date.today(), 'user_hash': None,
'value': {'count': 1, 'app-id': 234}},
{'key': key, 'recorded': datetime.date.today(), 'user_hash': None,
'value': {'count': 1, 'app-id': 345}},
]
res = self.client.get(self.list_url, data={'key': key, 'limit': 2})
eq_(res.status_code, 200)
data = json.loads(res.content)
eq_(len(data['objects']), 2)
ok_(data['meta']['next'] is not None)
ok_(data['meta']['previous'] is None)
eq_(data['meta']['total_count'], 3)
eq_(data['meta']['offset'], 0)
eq_(data['meta']['limit'], 2)
eq_(data['objects'][0]['value']['app-id'], 123)
eq_(data['objects'][1]['value']['app-id'], 234)
res = self.client.get(self.list_url, data={'key': key, 'limit': 2,
'offset': 2})
eq_(res.status_code, 200)
data = json.loads(res.content)
eq_(len(data['objects']), 1)
eq_(data['objects'][0]['value']['app-id'], 345)
ok_(data['meta']['next'] is None)
ok_(data['meta']['previous'] is not None)
eq_(data['meta']['total_count'], 3)
eq_(data['meta']['offset'], 2)
eq_(data['meta']['limit'], 2)
def test_pagination(self):
record_stat('app.install', self.request, value=2)
record_stat('app.install', self.request, value=4)
record_stat('app.install', self.request, value=6)
res = self.client.get(self.list_url, data={'limit': 2})
eq_(res.status_code, 200)
data = json.loads(res.content)
eq_(len(data['objects']), 2)
ok_(data['meta']['next'] is not None)
ok_(data['meta']['previous'] is None)
eq_(data['meta']['total_count'], 3)
eq_(data['meta']['offset'], 0)
eq_(data['meta']['limit'], 2)
class TestDateRange(TestCase):
def setUp(self):
self.today = datetime.datetime.now().replace(microsecond=0)
self.week_ago = self.days_ago(7)
def test_date_range(self):
range = list(daterange(self.week_ago, self.today))
eq_(len(range), 7)
eq_(range[0], self.week_ago)
ok_(self.today not in range)

Просмотреть файл

@ -1,8 +0,0 @@
from django.conf.urls import patterns, url
from .resources import MonolithView
urlpatterns = patterns('',
url(r'^monolith/data/', MonolithView.as_view(), name='monolith-list'),
)

Просмотреть файл

@ -59,7 +59,6 @@ heka-py==0.30.3
heka-py-cef==0.3.1
heka-py-raven==0.6
mock==1.0.1
monolith.client==0.9
moz-addon-packager==1.0.1
mozilla-logger==0.2
mozpay==2.0.0

Просмотреть файл

@ -38,7 +38,6 @@ HOME=/tmp
#once per day
05 8 * * * %(z_cron)s email_daily_ratings --settings=settings_local_mkt
10 8 * * * %(z_cron)s update_monolith_stats `/bin/date -d 'yesterday' +\%%Y-\%%m-\%%d`
15 8 * * * %(z_cron)s process_iarc_changes --settings=settings_local_mkt
30 8 * * * %(z_cron)s dump_user_installs_cron --settings=settings_local_mkt
00 9 * * * %(z_cron)s update_app_downloads --settings=settings_local_mkt

Просмотреть файл

@ -186,8 +186,6 @@ ALLOW_SELF_REVIEWS = True
GOOGLE_ANALYTICS_CREDENTIALS = private.GOOGLE_ANALYTICS_CREDENTIALS
GOOGLE_API_CREDENTIALS = private.GOOGLE_API_CREDENTIALS
MONOLITH_SERVER = 'https://monolith-dev.allizom.org'
GEOIP_URL = 'http://geo-dev.marketplace.allizom.org'
AWS_ACCESS_KEY_ID = private.AWS_ACCESS_KEY_ID

Просмотреть файл

@ -187,8 +187,6 @@ ALLOW_SELF_REVIEWS = True
GOOGLE_ANALYTICS_CREDENTIALS = private.GOOGLE_ANALYTICS_CREDENTIALS
GOOGLE_API_CREDENTIALS = private.GOOGLE_API_CREDENTIALS
MONOLITH_SERVER = 'https://monolith-dev.allizom.org'
GEOIP_URL = 'https://geo-dev-marketplace.allizom.org'
AWS_ACCESS_KEY_ID = private.AWS_ACCESS_KEY_ID

Просмотреть файл

@ -178,8 +178,6 @@ XSENDFILE_HEADER = 'X-Accel-Redirect'
ALLOW_SELF_REVIEWS = True
MONOLITH_SERVER = 'https://monolith.allizom.org'
GEOIP_URL = 'http://geo.marketplace.allizom.org'
API_THROTTLE = False

Просмотреть файл

@ -169,8 +169,6 @@ XSENDFILE_HEADER = 'X-Accel-Redirect'
GOOGLE_ANALYTICS_CREDENTIALS = private.GOOGLE_ANALYTICS_CREDENTIALS
GOOGLE_API_CREDENTIALS = private.GOOGLE_API_CREDENTIALS
MONOLITH_SERVER = 'https://monolith.firefox.com'
GEOIP_URL = 'http://geo.marketplace.firefox.com'
NEWRELIC_WHITELIST = ['web1.addons.phx1.mozilla.com',

Просмотреть файл

@ -178,8 +178,6 @@ XSENDFILE_HEADER = 'X-Accel-Redirect'
ALLOW_SELF_REVIEWS = True
MONOLITH_SERVER = 'https://monolith.allizom.org'
GEOIP_URL = 'http://geo.marketplace.allizom.org'
API_THROTTLE = False