Merge lp:~bac/charmworld/add-stats-to-api into lp:charmworld

Proposed by Brad Crittenden
Status: Merged
Approved by: Brad Crittenden
Approved revision: 469
Merged at revision: 467
Proposed branch: lp:~bac/charmworld/add-stats-to-api
Merge into: lp:charmworld
Diff against target: 195 lines (+56/-31)
5 files modified
charmworld/views/api/__init__.py (+10/-1)
charmworld/views/bundles.py (+3/-21)
charmworld/views/tests/test_api.py (+16/-8)
charmworld/views/tests/test_bundles.py (+3/-1)
charmworld/views/utils.py (+24/-0)
To merge this branch: bzr merge lp:~bac/charmworld/add-stats-to-api
Reviewer Review Type Date Requested Status
Juju Gui Bot continuous-integration Approve
Charmworld Developers Pending
Review via email: mp+195991@code.launchpad.net

Commit message

Add download stats to bundle API call.

https://codereview.appspot.com/29850043/

R=benji

Description of the change

Add download stats to bundle API call.

https://codereview.appspot.com/29850043/

To post a comment you must log in.
Revision history for this message
Brad Crittenden (bac) wrote :
Download full text (7.5 KiB)

Reviewers: mp+195991_code.launchpad.net,

Message:
Please take a look.

Description:
Add download stats to bundle API call.

https://code.launchpad.net/~bac/charmworld/add-stats-to-api/+merge/195991

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/29850043/

Affected files (+58, -31 lines):
   A [revision details]
   M charmworld/views/api/__init__.py
   M charmworld/views/bundles.py
   M charmworld/views/tests/test_api.py
   M charmworld/views/tests/test_bundles.py
   M charmworld/views/utils.py

Index: [revision details]
=== added file '[revision details]'
--- [revision details] 2012-01-01 00:00:00 +0000
+++ [revision details] 2012-01-01 00:00:00 +0000
@@ -0,0 +1,2 @@
+Old revision: tarmac-20131119203355-yu8j8hqzmyv8f9d1
+New revision: <email address hidden>

Index: charmworld/views/bundles.py
=== modified file 'charmworld/views/bundles.py'
--- charmworld/views/bundles.py 2013-11-13 17:40:11 +0000
+++ charmworld/views/bundles.py 2013-11-20 18:08:03 +0000
@@ -8,12 +8,8 @@
  from charmworld import cached_view_config
  from charmworld.models import (
      Bundle,
- DatedMetricSource,
-)
-from charmworld.utils import (
- build_metric_key,
- utc_today,
-)
+)
+from charmworld.views.utils import get_bundle_downloads
  from charmworld.views.api import json_response
  from charmworld.views.helpers import (
      find_bundle,
@@ -29,17 +25,6 @@
  SUPPORTED_README_EXTS = ('', '.txt', '.md', '.markdown', '.mkd', '.rst')

-class Statistics:
- """A template helper that wraps a DatedMetric instance."""
-
- def __init__(self, metric, day=None):
- day = day or utc_today()
- self.past_7_days = metric.get_range_total(7, day)
- self.past_30_days = metric.get_range_total(30, day)
- self.past_half_year = metric.get_range_total(365 / 2, day)
- self.total = metric.get_total()
-
-
  class BundleDetail(Bundle):

      service_keys = (
@@ -113,11 +98,8 @@

  def _bundle_view(request, bundle):
- source = DatedMetricSource.from_db(request.db)
- metric_key = build_metric_key('deployments', bundle.id)
- metric = source.retrieve(metric_key, create=True)
+ downloads = get_bundle_downloads(request.db, bundle.id)
      bundle = BundleDetail(dict(bundle))
- downloads = Statistics(metric)
      try:
          is_owner = bool((request.user is not None) and
                          (request.user.nickname == bundle.owner))

Index: charmworld/views/utils.py
=== modified file 'charmworld/views/utils.py'
--- charmworld/views/utils.py 2013-10-20 19:09:02 +0000
+++ charmworld/views/utils.py 2013-11-20 17:16:29 +0000
@@ -1,5 +1,10 @@
  import json
  from webob import Response
+from charmworld.models import DatedMetricSource
+from charmworld.utils import (
+ build_metric_key,
+ utc_today,
+)

  def json_response(status, value, headers=[]):
@@ -31,3 +36,22 @@

('Access-Control-Allow-Headers', 'X-Requested-With'),
                      ] + headers,
                      status_code=status)
+
+
+class Statistics:
+ """A template helper that wraps a DatedMetric instance."""
+
+ def __init__(self, me...

Read more...

Revision history for this message
Benji York (benji) wrote :
lp:~bac/charmworld/add-stats-to-api updated
469. By Brad Crittenden

Merge from trunk

Revision history for this message
Juju Gui Bot (juju-gui-bot) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'charmworld/views/api/__init__.py'
2--- charmworld/views/api/__init__.py 2013-11-13 17:40:11 +0000
3+++ charmworld/views/api/__init__.py 2013-11-20 19:36:54 +0000
4@@ -45,7 +45,10 @@
5 timestamp,
6 )
7 from charmworld.views.api.proof import proof_deployer
8-from charmworld.views.utils import json_response
9+from charmworld.views.utils import (
10+ get_bundle_downloads,
11+ json_response,
12+)
13
14
15 @view_config(route_name="search-json-obsolete")
16@@ -428,6 +431,12 @@
17 owner=bundle_dict['owner'],
18 rev=bundle_dict['basket_revision'],
19 )
20+
21+ # Add in download data.
22+ downloads = get_bundle_downloads(db, bundle.id)
23+ bundle_dict['downloads'] = downloads.total
24+ bundle_dict['downloads_in_past_30_days'] = downloads.past_30_days
25+
26 service_data = bundle_dict.get('data')
27 # Now load the charm information we require for the services in the
28 # bundle.
29
30=== modified file 'charmworld/views/bundles.py'
31--- charmworld/views/bundles.py 2013-11-13 17:40:11 +0000
32+++ charmworld/views/bundles.py 2013-11-20 19:36:54 +0000
33@@ -8,12 +8,8 @@
34 from charmworld import cached_view_config
35 from charmworld.models import (
36 Bundle,
37- DatedMetricSource,
38-)
39-from charmworld.utils import (
40- build_metric_key,
41- utc_today,
42-)
43+)
44+from charmworld.views.utils import get_bundle_downloads
45 from charmworld.views.api import json_response
46 from charmworld.views.helpers import (
47 find_bundle,
48@@ -29,17 +25,6 @@
49 SUPPORTED_README_EXTS = ('', '.txt', '.md', '.markdown', '.mkd', '.rst')
50
51
52-class Statistics:
53- """A template helper that wraps a DatedMetric instance."""
54-
55- def __init__(self, metric, day=None):
56- day = day or utc_today()
57- self.past_7_days = metric.get_range_total(7, day)
58- self.past_30_days = metric.get_range_total(30, day)
59- self.past_half_year = metric.get_range_total(365 / 2, day)
60- self.total = metric.get_total()
61-
62-
63 class BundleDetail(Bundle):
64
65 service_keys = (
66@@ -113,11 +98,8 @@
67
68
69 def _bundle_view(request, bundle):
70- source = DatedMetricSource.from_db(request.db)
71- metric_key = build_metric_key('deployments', bundle.id)
72- metric = source.retrieve(metric_key, create=True)
73+ downloads = get_bundle_downloads(request.db, bundle.id)
74 bundle = BundleDetail(dict(bundle))
75- downloads = Statistics(metric)
76 try:
77 is_owner = bool((request.user is not None) and
78 (request.user.nickname == bundle.owner))
79
80=== modified file 'charmworld/views/tests/test_api.py'
81--- charmworld/views/tests/test_api.py 2013-11-08 19:14:29 +0000
82+++ charmworld/views/tests/test_api.py 2013-11-20 19:36:54 +0000
83@@ -786,23 +786,29 @@
84 response = self.get_response('bundle', 'byobu/bat')
85 self.assertEqual(200, response.status_code)
86
87- def test_results_match(self):
88+ def test_results_are_correct(self):
89 self.enable_routes()
90 # Make the charm that we'll use as a service.
91- _id, charm = factory.makeCharm(
92- self.db,
93- description=''
94- )
95+ _id, charm = factory.makeCharm(self.db, description='')
96 services = {
97 u'charm': {
98 u'branch': charm['branch_spec'],
99- u'charm': charm['name']
100+ u'charm': charm['name'],
101 }
102 }
103 self.makeBundle(
104 name='bat', owner='bac',
105 basket_with_rev='byobu/4', services=services)
106- response = self.get_response('bundle', '~bac/byobu/4/bat')
107+
108+ class FakeObject(object):
109+ pass
110+
111+ fake_stat = FakeObject
112+ fake_stat.total = 10
113+ fake_stat.past_30_days = 5
114+ mock_path = 'charmworld.views.api.get_bundle_downloads'
115+ with patch(mock_path, return_value=fake_stat):
116+ response = self.get_response('bundle', '~bac/byobu/4/bat')
117 self.assertEqual(200, response.status_code)
118 deployer_url = u'http://example.com/bundle/%7Ebac/byobu/4/bat/json'
119 self.assertEqual(
120@@ -812,7 +818,7 @@
121 u'basket_revision': 4,
122 u'branch_deleted': False,
123 u'charm_metadata': {
124- u'charm': self.api_class._format_charm(Charm(charm))
125+ u'charm': self.api_class._format_charm(Charm(charm)),
126 },
127 u'data': {
128 u'series': u'precise',
129@@ -837,6 +843,8 @@
130 u'promulgated': False,
131 u'title': u'',
132 u'deployer_file_url': deployer_url,
133+ u'downloads': 10,
134+ u'downloads_in_past_30_days': 5,
135 })
136
137 def test_extracting_bundle_id_with_trailing_full_id(self):
138
139=== modified file 'charmworld/views/tests/test_bundles.py'
140--- charmworld/views/tests/test_bundles.py 2013-11-13 17:40:11 +0000
141+++ charmworld/views/tests/test_bundles.py 2013-11-20 19:36:54 +0000
142@@ -17,12 +17,14 @@
143 )
144 from charmworld.views.bundles import (
145 BundleDetail,
146- Statistics,
147 find_bundle,
148 official_bundle_json,
149 personal_bundle,
150 personal_bundle_json,
151 )
152+from charmworld.views.utils import (
153+ Statistics,
154+)
155
156
157 class TestBundleDetail(ViewTestBase):
158
159=== modified file 'charmworld/views/utils.py'
160--- charmworld/views/utils.py 2013-10-20 19:09:02 +0000
161+++ charmworld/views/utils.py 2013-11-20 19:36:54 +0000
162@@ -1,5 +1,10 @@
163 import json
164 from webob import Response
165+from charmworld.models import DatedMetricSource
166+from charmworld.utils import (
167+ build_metric_key,
168+ utc_today,
169+)
170
171
172 def json_response(status, value, headers=[]):
173@@ -31,3 +36,22 @@
174 ('Access-Control-Allow-Headers', 'X-Requested-With'),
175 ] + headers,
176 status_code=status)
177+
178+
179+class Statistics:
180+ """A template helper that wraps a DatedMetric instance."""
181+
182+ def __init__(self, metric, day=None):
183+ day = day or utc_today()
184+ self.past_7_days = metric.get_range_total(7, day)
185+ self.past_30_days = metric.get_range_total(30, day)
186+ self.past_half_year = metric.get_range_total(365 / 2, day)
187+ self.total = metric.get_total()
188+
189+
190+def get_bundle_downloads(db, bundle_id):
191+ """Return a Statistics object for the bundle's downloads."""
192+ source = DatedMetricSource.from_db(db)
193+ metric_key = build_metric_key('deployments', bundle_id)
194+ metric = source.retrieve(metric_key, create=True)
195+ return Statistics(metric)

Subscribers

People subscribed via source and target branches

to all changes: