Merge lp:~michael.nelson/ubuntu-webcatalog/1019326-missing-ratings-summary into lp:ubuntu-webcatalog

Proposed by Michael Nelson
Status: Merged
Approved by: Michael Nelson
Approved revision: 182
Merged at revision: 174
Proposed branch: lp:~michael.nelson/ubuntu-webcatalog/1019326-missing-ratings-summary
Merge into: lp:ubuntu-webcatalog
Diff against target: 256 lines (+100/-25)
6 files modified
src/webcatalog/admin.py (+6/-0)
src/webcatalog/management/commands/import_all_ratings_stats.py (+13/-1)
src/webcatalog/management/commands/import_ratings_stats.py (+25/-13)
src/webcatalog/tasks.py (+7/-1)
src/webcatalog/tests/test_commands.py (+44/-9)
src/webcatalog/tests/test_views.py (+5/-1)
To merge this branch: bzr merge lp:~michael.nelson/ubuntu-webcatalog/1019326-missing-ratings-summary
Reviewer Review Type Date Requested Status
Łukasz Czyżykowski (community) Approve
Review via email: mp+137619@code.launchpad.net

Commit message

Add admin class for ReviewStatsImport and optional --download-all flag for import_ratings_stats.

Description of the change

After some investigation on bug 1015604, this branch adds:

1) An admin class for ReviewStatsImport, so we can view/update when the last import occurred,
2) An --download-all flag for the import_ratings_stats command which forces all stats for the series to be downloaded, rather than requesting the optimised last X days,
3) An extra task so that we can request all ratings stats to be downloaded without needing a webop.

`fab test`

To post a comment you must log in.
Revision history for this message
Łukasz Czyżykowski (lukasz-czyzykowski) wrote :

All great

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/webcatalog/admin.py'
--- src/webcatalog/admin.py 2012-09-06 14:07:55 +0000
+++ src/webcatalog/admin.py 2012-12-03 17:04:22 +0000
@@ -28,6 +28,7 @@
28 DistroSeries,28 DistroSeries,
29 Exhibit,29 Exhibit,
30 Machine,30 Machine,
31 ReviewStatsImport,
31)32)
3233
33__metaclass__ = type34__metaclass__ = type
@@ -80,6 +81,10 @@
80 raw_id_fields = ('applications',)81 raw_id_fields = ('applications',)
8182
8283
84class ReviewStatsImportAdmin(admin.ModelAdmin):
85 list_display = ('distroseries', 'last_import')
86
87
83admin.site.register(Application, ApplicationAdmin)88admin.site.register(Application, ApplicationAdmin)
84admin.site.register(ApplicationMedia, ApplicationMediaAdmin)89admin.site.register(ApplicationMedia, ApplicationMediaAdmin)
85admin.site.register(ApplicationWidget, ApplicationWidgetAdmin)90admin.site.register(ApplicationWidget, ApplicationWidgetAdmin)
@@ -87,3 +92,4 @@
87admin.site.register(DistroSeries)92admin.site.register(DistroSeries)
88admin.site.register(Exhibit, ExhibitAdmin)93admin.site.register(Exhibit, ExhibitAdmin)
89admin.site.register(Machine, MachineAdmin)94admin.site.register(Machine, MachineAdmin)
95admin.site.register(ReviewStatsImport, ReviewStatsImportAdmin)
9096
=== modified file 'src/webcatalog/management/commands/import_all_ratings_stats.py'
--- src/webcatalog/management/commands/import_all_ratings_stats.py 2012-07-02 21:25:30 +0000
+++ src/webcatalog/management/commands/import_all_ratings_stats.py 2012-12-03 17:04:22 +0000
@@ -22,12 +22,23 @@
22__metaclass__ = type22__metaclass__ = type
23__all__ = []23__all__ = []
2424
25from optparse import make_option
26
25from django.conf import settings27from django.conf import settings
26from django.core.management import call_command28from django.core.management import call_command
27from django.core.management.base import NoArgsCommand29from django.core.management.base import NoArgsCommand
2830
2931
30class Command(NoArgsCommand):32class Command(NoArgsCommand):
33 option_list = NoArgsCommand.option_list + (
34 make_option(
35 '--download-all',
36 action='store_true',
37 dest='download_all',
38 default=False,
39 help='Download all ratings stats instead of stats since last '
40 'import.'),
41 )
3142
32 def handle_noargs(self, **options):43 def handle_noargs(self, **options):
33 self.verbosity = int(options['verbosity'])44 self.verbosity = int(options['verbosity'])
@@ -35,7 +46,8 @@
35 self.output("Importing ratings stats for {0}\n".format(46 self.output("Importing ratings stats for {0}\n".format(
36 distroseries), 1)47 distroseries), 1)
37 call_command('import_ratings_stats', distroseries,48 call_command('import_ratings_stats', distroseries,
38 verbosity=self.verbosity)49 verbosity=self.verbosity,
50 download_all=options['download_all'])
3951
40 def output(self, message, level=None, flush=False):52 def output(self, message, level=None, flush=False):
41 if hasattr(self, 'stdout'):53 if hasattr(self, 'stdout'):
4254
=== modified file 'src/webcatalog/management/commands/import_ratings_stats.py'
--- src/webcatalog/management/commands/import_ratings_stats.py 2012-06-19 13:10:25 +0000
+++ src/webcatalog/management/commands/import_ratings_stats.py 2012-12-03 17:04:22 +0000
@@ -17,11 +17,12 @@
1717
18"""Management command to import review statistics for a distroseries."""18"""Management command to import review statistics for a distroseries."""
1919
20import json
20from datetime import (21from datetime import (
21 datetime,22 datetime,
22 timedelta,23 timedelta,
23)24)
24import json25from optparse import make_option
2526
26from django.core.management.base import LabelCommand27from django.core.management.base import LabelCommand
2728
@@ -37,12 +38,22 @@
3738
3839
39class Command(LabelCommand):40class Command(LabelCommand):
41 option_list = LabelCommand.option_list + (
42 make_option(
43 '--download-all',
44 action='store_true',
45 dest='download_all',
46 default=False,
47 help='Download all ratings stats instead of stats since last '
48 'import.'),
49 )
4050
41 help = "Update application review statistics."51 help = "Update application review statistics."
42 verbosity = 152 verbosity = 1
4353
44 def handle_label(self, distroseries_name, **options):54 def handle_label(self, distroseries_name, **options):
45 self.verbosity = int(options['verbosity'])55 self.verbosity = int(options['verbosity'])
56 self.download_all = options['download_all']
46 # Check when we most recently imported review stats for this57 # Check when we most recently imported review stats for this
47 # distroseries.58 # distroseries.
48 distroseries, created = DistroSeries.objects.get_or_create(59 distroseries, created = DistroSeries.objects.get_or_create(
@@ -81,19 +92,20 @@
8192
82 def download_review_stats(self, distroseries):93 def download_review_stats(self, distroseries):
83 # Download the appropriate stats based on above.94 # Download the appropriate stats based on above.
84 other_imports = ReviewStatsImport.objects.filter(
85 distroseries=distroseries).order_by('-last_import')
86 num_days = None95 num_days = None
87 if other_imports:96 if not self.download_all:
88 stats_import = other_imports[0]97 other_imports = ReviewStatsImport.objects.filter(
89 time_since_last_import = (98 distroseries=distroseries).order_by('-last_import')
90 datetime.utcnow() - stats_import.last_import)99 if other_imports:
91 if time_since_last_import < timedelta(days=1):100 stats_import = other_imports[0]
92 num_days = 1101 time_since_last_import = (
93 elif time_since_last_import < timedelta(days=3):102 datetime.utcnow() - stats_import.last_import)
94 num_days = 3103 if time_since_last_import < timedelta(days=1):
95 elif time_since_last_import < timedelta(days=7):104 num_days = 1
96 num_days = 7105 elif time_since_last_import < timedelta(days=3):
106 num_days = 3
107 elif time_since_last_import < timedelta(days=7):
108 num_days = 7
97109
98 # Currently we have ratings in rnr for ubuntu and for-purchase110 # Currently we have ratings in rnr for ubuntu and for-purchase
99 # PPAs only, so we set origin to any. If we later support reviews111 # PPAs only, so we set origin to any. If we later support reviews
100112
=== modified file 'src/webcatalog/tasks.py'
--- src/webcatalog/tasks.py 2012-06-29 19:51:06 +0000
+++ src/webcatalog/tasks.py 2012-12-03 17:04:22 +0000
@@ -25,10 +25,16 @@
2525
26@task(name="webcatalog.tasks.import_ratings_stats")26@task(name="webcatalog.tasks.import_ratings_stats")
27def import_ratings_stats():27def import_ratings_stats():
28 """Import all ratings and reviews data"""28 """Import ratings data since the last import"""
29 call_command('import_all_ratings_stats', verbosity=0)29 call_command('import_all_ratings_stats', verbosity=0)
3030
3131
32@task(name="webcatalog.tasks.import_ratings_stats_all")
33def import_ratings_stats_all():
34 """Import all ratings data"""
35 call_command('import_all_ratings_stats', verbosity=0, download_all=True)
36
37
32@task(name="webcatalog.tasks.check_all_latest")38@task(name="webcatalog.tasks.check_all_latest")
33def check_all_latest():39def check_all_latest():
34 """Update the 'is_latest' bit on all Applications"""40 """Update the 'is_latest' bit on all Applications"""
3541
=== modified file 'src/webcatalog/tests/test_commands.py'
--- src/webcatalog/tests/test_commands.py 2012-08-29 21:46:54 +0000
+++ src/webcatalog/tests/test_commands.py 2012-12-03 17:04:22 +0000
@@ -38,6 +38,7 @@
38from django.test.testcases import TransactionTestCase38from django.test.testcases import TransactionTestCase
3939
40from mock import (40from mock import (
41 call,
41 patch,42 patch,
42 MagicMock,43 MagicMock,
43 Mock,44 Mock,
@@ -773,6 +774,19 @@
773 self.mock_review_stats.assert_called_with(774 self.mock_review_stats.assert_called_with(
774 origin='any', distroseries='onion', days=3)775 origin='any', distroseries='onion', days=3)
775776
777 def test_force_download_all_stats(self):
778 # If the download_all option is used, all stats are
779 # downloaded, rather than the optimised last X days.
780 onion = self.factory.make_distroseries(code_name='onion')
781 orig_timestamp = datetime.utcnow() - timedelta(2)
782 import_record = ReviewStatsImport.objects.create(
783 distroseries=onion, last_import=orig_timestamp)
784
785 call_command('import_ratings_stats', 'onion', download_all=True)
786
787 self.mock_review_stats.assert_called_with(origin='any',
788 distroseries='onion')
789
776 def test_update_app_stats(self):790 def test_update_app_stats(self):
777 # Any stats provided in the api call will be used to update our791 # Any stats provided in the api call will be used to update our
778 # apps in the db.792 # apps in the db.
@@ -1106,12 +1120,33 @@
11061120
11071121
1108class ImportAllRatingsStatsTestCase(TestCaseWithFactory):1122class ImportAllRatingsStatsTestCase(TestCaseWithFactory):
1109 @patch('sys.stdout')1123
1110 def test_handle(self, mock_stdout):1124 def setUp(self):
1111 patch_attr = ('webcatalog.management.commands.'1125 patcher = patch('webcatalog.management.commands.'
1112 'import_all_ratings_stats.call_command')1126 'import_all_ratings_stats.call_command')
1113 with patch_settings(UBUNTU_SERIES_FOR_VERSIONS=TEST_VERSIONS):1127 self.mock_call_command = patcher.start()
1114 with patch(patch_attr) as mock_call_command:1128 self.addCleanup(patcher.stop)
1115 call_command('import_all_ratings_stats')1129
11161130 patcher = patch('sys.stdout')
1117 self.assertEqual(mock_call_command.call_count, len(TEST_VERSIONS))1131 patcher.start()
1132 self.addCleanup(patcher.stop)
1133
1134 def test_handle_download(self):
1135 with patch_settings(UBUNTU_SERIES_FOR_VERSIONS=TEST_VERSIONS):
1136 call_command('import_all_ratings_stats')
1137
1138 expected_calls = [
1139 call('import_ratings_stats', series, verbosity=1,
1140 download_all=False) for series in TEST_VERSIONS.values()]
1141 self.mock_call_command.assert_has_calls(expected_calls,
1142 any_order=True)
1143
1144 def test_handle_download_all(self):
1145 with patch_settings(UBUNTU_SERIES_FOR_VERSIONS=TEST_VERSIONS):
1146 call_command('import_all_ratings_stats', download_all=True)
1147
1148 expected_calls = [
1149 call('import_ratings_stats', series, verbosity=1,
1150 download_all=True) for series in TEST_VERSIONS.values()]
1151 self.mock_call_command.assert_has_calls(expected_calls,
1152 any_order=True)
11181153
=== modified file 'src/webcatalog/tests/test_views.py'
--- src/webcatalog/tests/test_views.py 2012-09-06 14:07:55 +0000
+++ src/webcatalog/tests/test_views.py 2012-12-03 17:04:22 +0000
@@ -1394,10 +1394,14 @@
1394 'name': 'import_sca',1394 'name': 'import_sca',
1395 },1395 },
1396 {1396 {
1397 'doc': 'Import all ratings and reviews data',1397 'doc': 'Import ratings data since the last import',
1398 'name': 'import_ratings_stats',1398 'name': 'import_ratings_stats',
1399 },1399 },
1400 {1400 {
1401 'doc': 'Import all ratings data',
1402 'name': 'import_ratings_stats_all',
1403 },
1404 {
1401 'doc': "Update the 'is_latest' bit on all Applications",1405 'doc': "Update the 'is_latest' bit on all Applications",
1402 'name': 'check_all_latest',1406 'name': 'check_all_latest',
1403 },1407 },

Subscribers

People subscribed via source and target branches