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
=== modified file 'charmworld/views/api/__init__.py'
--- charmworld/views/api/__init__.py 2013-11-13 17:40:11 +0000
+++ charmworld/views/api/__init__.py 2013-11-20 19:36:54 +0000
@@ -45,7 +45,10 @@
45 timestamp,45 timestamp,
46)46)
47from charmworld.views.api.proof import proof_deployer47from charmworld.views.api.proof import proof_deployer
48from charmworld.views.utils import json_response48from charmworld.views.utils import (
49 get_bundle_downloads,
50 json_response,
51)
4952
5053
51@view_config(route_name="search-json-obsolete")54@view_config(route_name="search-json-obsolete")
@@ -428,6 +431,12 @@
428 owner=bundle_dict['owner'],431 owner=bundle_dict['owner'],
429 rev=bundle_dict['basket_revision'],432 rev=bundle_dict['basket_revision'],
430 )433 )
434
435 # Add in download data.
436 downloads = get_bundle_downloads(db, bundle.id)
437 bundle_dict['downloads'] = downloads.total
438 bundle_dict['downloads_in_past_30_days'] = downloads.past_30_days
439
431 service_data = bundle_dict.get('data')440 service_data = bundle_dict.get('data')
432 # Now load the charm information we require for the services in the441 # Now load the charm information we require for the services in the
433 # bundle.442 # bundle.
434443
=== modified file 'charmworld/views/bundles.py'
--- charmworld/views/bundles.py 2013-11-13 17:40:11 +0000
+++ charmworld/views/bundles.py 2013-11-20 19:36:54 +0000
@@ -8,12 +8,8 @@
8from charmworld import cached_view_config8from charmworld import cached_view_config
9from charmworld.models import (9from charmworld.models import (
10 Bundle,10 Bundle,
11 DatedMetricSource,11)
12)12from charmworld.views.utils import get_bundle_downloads
13from charmworld.utils import (
14 build_metric_key,
15 utc_today,
16)
17from charmworld.views.api import json_response13from charmworld.views.api import json_response
18from charmworld.views.helpers import (14from charmworld.views.helpers import (
19 find_bundle,15 find_bundle,
@@ -29,17 +25,6 @@
29SUPPORTED_README_EXTS = ('', '.txt', '.md', '.markdown', '.mkd', '.rst')25SUPPORTED_README_EXTS = ('', '.txt', '.md', '.markdown', '.mkd', '.rst')
3026
3127
32class Statistics:
33 """A template helper that wraps a DatedMetric instance."""
34
35 def __init__(self, metric, day=None):
36 day = day or utc_today()
37 self.past_7_days = metric.get_range_total(7, day)
38 self.past_30_days = metric.get_range_total(30, day)
39 self.past_half_year = metric.get_range_total(365 / 2, day)
40 self.total = metric.get_total()
41
42
43class BundleDetail(Bundle):28class BundleDetail(Bundle):
4429
45 service_keys = (30 service_keys = (
@@ -113,11 +98,8 @@
11398
11499
115def _bundle_view(request, bundle):100def _bundle_view(request, bundle):
116 source = DatedMetricSource.from_db(request.db)101 downloads = get_bundle_downloads(request.db, bundle.id)
117 metric_key = build_metric_key('deployments', bundle.id)
118 metric = source.retrieve(metric_key, create=True)
119 bundle = BundleDetail(dict(bundle))102 bundle = BundleDetail(dict(bundle))
120 downloads = Statistics(metric)
121 try:103 try:
122 is_owner = bool((request.user is not None) and104 is_owner = bool((request.user is not None) and
123 (request.user.nickname == bundle.owner))105 (request.user.nickname == bundle.owner))
124106
=== modified file 'charmworld/views/tests/test_api.py'
--- charmworld/views/tests/test_api.py 2013-11-08 19:14:29 +0000
+++ charmworld/views/tests/test_api.py 2013-11-20 19:36:54 +0000
@@ -786,23 +786,29 @@
786 response = self.get_response('bundle', 'byobu/bat')786 response = self.get_response('bundle', 'byobu/bat')
787 self.assertEqual(200, response.status_code)787 self.assertEqual(200, response.status_code)
788788
789 def test_results_match(self):789 def test_results_are_correct(self):
790 self.enable_routes()790 self.enable_routes()
791 # Make the charm that we'll use as a service.791 # Make the charm that we'll use as a service.
792 _id, charm = factory.makeCharm(792 _id, charm = factory.makeCharm(self.db, description='')
793 self.db,
794 description=''
795 )
796 services = {793 services = {
797 u'charm': {794 u'charm': {
798 u'branch': charm['branch_spec'],795 u'branch': charm['branch_spec'],
799 u'charm': charm['name']796 u'charm': charm['name'],
800 }797 }
801 }798 }
802 self.makeBundle(799 self.makeBundle(
803 name='bat', owner='bac',800 name='bat', owner='bac',
804 basket_with_rev='byobu/4', services=services)801 basket_with_rev='byobu/4', services=services)
805 response = self.get_response('bundle', '~bac/byobu/4/bat')802
803 class FakeObject(object):
804 pass
805
806 fake_stat = FakeObject
807 fake_stat.total = 10
808 fake_stat.past_30_days = 5
809 mock_path = 'charmworld.views.api.get_bundle_downloads'
810 with patch(mock_path, return_value=fake_stat):
811 response = self.get_response('bundle', '~bac/byobu/4/bat')
806 self.assertEqual(200, response.status_code)812 self.assertEqual(200, response.status_code)
807 deployer_url = u'http://example.com/bundle/%7Ebac/byobu/4/bat/json'813 deployer_url = u'http://example.com/bundle/%7Ebac/byobu/4/bat/json'
808 self.assertEqual(814 self.assertEqual(
@@ -812,7 +818,7 @@
812 u'basket_revision': 4,818 u'basket_revision': 4,
813 u'branch_deleted': False,819 u'branch_deleted': False,
814 u'charm_metadata': {820 u'charm_metadata': {
815 u'charm': self.api_class._format_charm(Charm(charm))821 u'charm': self.api_class._format_charm(Charm(charm)),
816 },822 },
817 u'data': {823 u'data': {
818 u'series': u'precise',824 u'series': u'precise',
@@ -837,6 +843,8 @@
837 u'promulgated': False,843 u'promulgated': False,
838 u'title': u'',844 u'title': u'',
839 u'deployer_file_url': deployer_url,845 u'deployer_file_url': deployer_url,
846 u'downloads': 10,
847 u'downloads_in_past_30_days': 5,
840 })848 })
841849
842 def test_extracting_bundle_id_with_trailing_full_id(self):850 def test_extracting_bundle_id_with_trailing_full_id(self):
843851
=== modified file 'charmworld/views/tests/test_bundles.py'
--- charmworld/views/tests/test_bundles.py 2013-11-13 17:40:11 +0000
+++ charmworld/views/tests/test_bundles.py 2013-11-20 19:36:54 +0000
@@ -17,12 +17,14 @@
17)17)
18from charmworld.views.bundles import (18from charmworld.views.bundles import (
19 BundleDetail,19 BundleDetail,
20 Statistics,
21 find_bundle,20 find_bundle,
22 official_bundle_json,21 official_bundle_json,
23 personal_bundle,22 personal_bundle,
24 personal_bundle_json,23 personal_bundle_json,
25)24)
25from charmworld.views.utils import (
26 Statistics,
27)
2628
2729
28class TestBundleDetail(ViewTestBase):30class TestBundleDetail(ViewTestBase):
2931
=== modified file 'charmworld/views/utils.py'
--- charmworld/views/utils.py 2013-10-20 19:09:02 +0000
+++ charmworld/views/utils.py 2013-11-20 19:36:54 +0000
@@ -1,5 +1,10 @@
1import json1import json
2from webob import Response2from webob import Response
3from charmworld.models import DatedMetricSource
4from charmworld.utils import (
5 build_metric_key,
6 utc_today,
7)
38
49
5def json_response(status, value, headers=[]):10def json_response(status, value, headers=[]):
@@ -31,3 +36,22 @@
31 ('Access-Control-Allow-Headers', 'X-Requested-With'),36 ('Access-Control-Allow-Headers', 'X-Requested-With'),
32 ] + headers,37 ] + headers,
33 status_code=status)38 status_code=status)
39
40
41class Statistics:
42 """A template helper that wraps a DatedMetric instance."""
43
44 def __init__(self, metric, day=None):
45 day = day or utc_today()
46 self.past_7_days = metric.get_range_total(7, day)
47 self.past_30_days = metric.get_range_total(30, day)
48 self.past_half_year = metric.get_range_total(365 / 2, day)
49 self.total = metric.get_total()
50
51
52def get_bundle_downloads(db, bundle_id):
53 """Return a Statistics object for the bundle's downloads."""
54 source = DatedMetricSource.from_db(db)
55 metric_key = build_metric_key('deployments', bundle_id)
56 metric = source.retrieve(metric_key, create=True)
57 return Statistics(metric)

Subscribers

People subscribed via source and target branches

to all changes: