From cfd922f2737171e30e1691e10dbf7ae04b47572f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Stefan=20K=C3=B6gl?= Date: Sat, 21 Jun 2014 19:22:26 +0200 Subject: [PATCH] [Migration] remove episode_for_podcast_url --- mygpo/api/advanced/directory.py | 12 ++++++------ mygpo/api/advanced/episode.py | 11 ++++++----- mygpo/api/advanced/settings.py | 9 +++++---- mygpo/api/tests.py | 39 ++++++++++++++++++++++++++++++++++++--- mygpo/api/urls.py | 2 +- mygpo/db/couchdb/episode.py | 22 ---------------------- mygpo/test.py | 16 ++++++++++++++++ mygpo/web/tests.py | 21 ++++++--------------- 8 files changed, 76 insertions(+), 56 deletions(-) diff --git a/mygpo/api/advanced/directory.py b/mygpo/api/advanced/directory.py index ae79604c..87e38cb0 100644 --- a/mygpo/api/advanced/directory.py +++ b/mygpo/api/advanced/directory.py @@ -22,15 +22,13 @@ from django.views.decorators.csrf import csrf_exempt from django.views.decorators.cache import cache_page from django.shortcuts import get_object_or_404 -from mygpo.core import models -from mygpo.podcasts.models import Podcast +from mygpo.podcasts.models import Podcast, Episode from mygpo.utils import parse_range, normalize_feed_url from mygpo.directory.tags import Topics from mygpo.web.utils import get_episode_link_target, get_podcast_link_target from mygpo.web.logo import get_logo_url from mygpo.decorators import cors_origin from mygpo.api.httpresponse import JsonResponse -from mygpo.db.couchdb.episode import episode_for_podcast_url from mygpo.db.couchdb.directory import category_for_tag @@ -87,9 +85,11 @@ def episode_info(request): if not podcast_url or not episode_url: raise Http404 - episode = episode_for_podcast_url(podcast_url, episode_url) - - if episode is None: + try: + query = Episode.objects.filter(podcast__urls__url=podcast_url, + urls__url=episode_url) + episode = query.select_related('podcast').get() + except Episode.DoesNotExist: raise Http404 domain = RequestSite(request).domain diff --git a/mygpo/api/advanced/episode.py b/mygpo/api/advanced/episode.py index 87d1ddb9..d391c330 100644 --- a/mygpo/api/advanced/episode.py +++ b/mygpo/api/advanced/episode.py @@ -32,7 +32,6 @@ from mygpo.users.models import Chapter from mygpo.utils import parse_time, parse_request_body, normalize_feed_url from mygpo.decorators import allowed_methods, cors_origin from mygpo.api.basic_auth import require_valid_user, check_username -from mygpo.db.couchdb.episode import episode_for_podcast_url from mygpo.db.couchdb.episode_state import episode_state_for_user_episode, \ update_episode_chapters @@ -102,9 +101,11 @@ def chapters(request, username): podcast_url = normalize_feed_url(podcast_url) episode_url = normalize_feed_url(episode_url) - episode = episode_for_podcast_url(podcast_url, episode_url) - if episode is None: + try: + episode = Episode.objects.filter(podcast__urls__url=podcast_url, + urls__url=episode_url).get() + except Episode.DoesNotExist: raise Http404 e_state = episode_state_for_user_episode(request.user, episode) @@ -141,8 +142,8 @@ def update_chapters(req, user): podcast_url = normalize_feed_url(req['podcast']) episode_url = normalize_feed_url(req['episode']) - episode = episode_for_podcast_url(podcast_url, episode_url, - create=True) + podcast = Podcast.objects.get_or_create_for_url(podcast_url) + episode = Episode.objects.get_or_create_for_url(podcast, episode_url) e_state = episode_state_for_user_episode(request.user, episode) diff --git a/mygpo/api/advanced/settings.py b/mygpo/api/advanced/settings.py index db000009..5c792b9d 100644 --- a/mygpo/api/advanced/settings.py +++ b/mygpo/api/advanced/settings.py @@ -21,13 +21,12 @@ from django.views.decorators.cache import never_cache from django.shortcuts import get_object_or_404 from mygpo.decorators import allowed_methods, cors_origin -from mygpo.podcasts.models import Podcast +from mygpo.podcasts.models import Podcast, Episode from mygpo.utils import parse_request_body from mygpo.api.basic_auth import require_valid_user, check_username from mygpo.api.httpresponse import JsonResponse from mygpo.users.models import PodcastUserState, DeviceDoesNotExist from mygpo.db.couchdb import get_main_database, get_userdata_database -from mygpo.db.couchdb.episode import episode_for_podcast_url from mygpo.db.couchdb.podcast_state import podcast_state_for_user_podcast from mygpo.db.couchdb.episode_state import episode_state_for_user_episode @@ -61,8 +60,10 @@ def main(request, username, scope): return obj, obj, udb def episode_settings(user, url, podcast_url): - episode = episode_for_podcast_url(podcast_url, url) - if episode is None: + try: + episode = Episode.objects.filter(podcast__urls__url=podcast_url, + urls__url=url).get() + except Episode.DoesNotExist: raise Http404 episode_state = episode_state_for_user_episode(user, episode) diff --git a/mygpo/api/tests.py b/mygpo/api/tests.py index e8271f2f..02f38bba 100644 --- a/mygpo/api/tests.py +++ b/mygpo/api/tests.py @@ -19,14 +19,17 @@ from __future__ import unicode_literals import unittest import doctest +from urllib import urlencode from copy import deepcopy from django.test.client import Client +from django.test import TestCase from django.core.urlresolvers import reverse +from mygpo.podcasts.models import Podcast, Episode from mygpo.api.advanced import episodes from mygpo.users.models import User -from mygpo.test import create_auth_string +from mygpo.test import create_auth_string, anon_request from mygpo.core.json import json @@ -34,7 +37,7 @@ class AdvancedAPITests(unittest.TestCase): def setUp(self): self.password = 'asdf' - self.username = 'user' + self.username = 'adv-api-user' self.user = User(username=self.username, email='user@example.com') self.user.set_password(self.password) self.user.save() @@ -110,7 +113,7 @@ class SubscriptionAPITests(unittest.TestCase): def setUp(self): self.password = 'asdf' - self.username = 'user' + self.username = 'subscription-api-user' self.device_uid = 'test-device' self.user = User(username=self.username, email='user@example.com') self.user.set_password(self.password) @@ -158,9 +161,39 @@ class SubscriptionAPITests(unittest.TestCase): self.assertEqual(response.status_code, 401, response.content) +class DirectoryTest(TestCase): + """ Test Directory API """ + + def setUp(self): + self.podcast = Podcast.objects.get_or_create_for_url( + 'http://example.com/directory-podcast.xml', + defaults = { + 'title': 'My Podcast', + }, + ) + self.episode = Episode.objects.get_or_create_for_url( + self.podcast, + 'http://example.com/directory-podcast/1.mp3', + defaults = { + 'title': 'My Episode', + }, + ) + + def test_episode_info(self): + """ Test that the expected number of queries is executed """ + url = reverse('api-episode-info') + '?' + urlencode( + (('podcast', self.podcast.url), ('url', self.episode.url))) + + with self.assertNumQueries(4): + resp = anon_request(url) + + self.assertEqual(resp.status_code, 200) + + def suite(): tl = unittest.TestLoader() suite = unittest.TestSuite() suite.addTest(tl.loadTestsFromTestCase(AdvancedAPITests)) suite.addTest(tl.loadTestsFromTestCase(SubscriptionAPITests)) + suite.addTest(tl.loadTestsFromTestCase(DirectoryTest)) return suite diff --git a/mygpo/api/urls.py b/mygpo/api/urls.py index 3c7f86cc..61c3f951 100644 --- a/mygpo/api/urls.py +++ b/mygpo/api/urls.py @@ -32,7 +32,7 @@ urlpatterns += patterns('mygpo.api.advanced', (r'^api/2/tags/(?P\d+)\.json', 'directory.top_tags'), (r'^api/2/tag/(?P[^/]+)/(?P\d+)\.json', 'directory.tag_podcasts'), (r'^api/2/data/podcast\.json', 'directory.podcast_info'), - (r'^api/2/data/episode\.json', 'directory.episode_info'), + url(r'^api/2/data/episode\.json', 'directory.episode_info', name='api-episode-info'), (r'^api/2/chapters/(?P[\w.-]+)\.json', 'episode.chapters'), (r'^api/2/updates/(?P[\w.-]+)/(?P[\w.-]+)\.json', diff --git a/mygpo/db/couchdb/episode.py b/mygpo/db/couchdb/episode.py index 39220302..e09696d4 100644 --- a/mygpo/db/couchdb/episode.py +++ b/mygpo/db/couchdb/episode.py @@ -17,28 +17,6 @@ import logging logger = logging.getLogger(__name__) -def episode_for_podcast_url(podcast_url, episode_url, create=False): - - if not podcast_url: - raise QueryParameterMissing('podcast_url') - - if not episode_url: - raise QueryParameterMissing('episode_url') - - - if create: - podcast = Podcast.objects.get_or_create_for_url(podcast_url) - - else: - try: - podcast = Podcast.objects.get(urls__url=podcast_url) - except Podcast.DoesNotExist: - # podcast does not exist and should not be created - return None - - return episode_for_podcast_id_url(podcast.id, episode_url, create) - - def episodes_to_dict(ids, use_cache=False): if ids is None: diff --git a/mygpo/test.py b/mygpo/test.py index c807a163..23b563f4 100644 --- a/mygpo/test.py +++ b/mygpo/test.py @@ -1,6 +1,9 @@ import os.path from django.conf import settings +from django.core.urlresolvers import resolve +from django.contrib.auth.models import AnonymousUser +from django.test.client import RequestFactory from couchdbkit import Database from couchdbkit.loaders import FileSystemDocsLoader @@ -46,3 +49,16 @@ def create_auth_string(username, password): credentials = base64.encodestring("%s:%s" % (username, password)).rstrip() auth_string = 'Basic %s' % credentials return auth_string + + +def anon_request(url): + """ Emulates an anonymous request, returns the response + + """ + factory = RequestFactory() + request = factory.get(url) + request.user = AnonymousUser() + view = resolve(url) + + response = view.func(request, *view.args, **view.kwargs) + return response diff --git a/mygpo/web/tests.py b/mygpo/web/tests.py index 3af0ca27..0e9d0b8f 100644 --- a/mygpo/web/tests.py +++ b/mygpo/web/tests.py @@ -20,14 +20,12 @@ import doctest import uuid from django.test import TestCase -from django.core.urlresolvers import reverse, resolve -from django.test.client import RequestFactory -from django.contrib.auth.models import AnonymousUser +from django.core.urlresolvers import reverse from mygpo.podcasts.models import Podcast, Episode, Slug import mygpo.web.utils from mygpo.users.models import User -from mygpo.test import create_auth_string +from mygpo.test import create_auth_string, anon_request class SimpleWebTests(TestCase): @@ -84,8 +82,6 @@ class PodcastPageTests(TestCase): """ Test the podcast page """ def setUp(self): - self.factory = RequestFactory() - # create a podcast and some episodes podcast = Podcast.objects.create(id=uuid.uuid1().hex) for n in range(20): @@ -107,22 +103,17 @@ class PodcastPageTests(TestCase): """ Test that the expected number of queries is executed """ url = reverse('podcast-slug', args=(self.podcast_slug.slug, )) # the number of queries must be independent of the number of episodes - self._check_queries_anon_page(url, 5) + with self.assertNumQueries(5): + anon_request(url) def test_episode_queries(self): """ Test that the expected number of queries is executed """ url = reverse('episode-slug', args=(self.podcast_slug.slug, self.episode_slug.slug)) - self._check_queries_anon_page(url, 5) - - def _check_queries_anon_page(self, url, num_queries): - request = self.factory.get(url) - request.user = AnonymousUser() - view = resolve(url) - with self.assertNumQueries(num_queries): - response = view.func(request, *view.args, **view.kwargs) + with self.assertNumQueries(5): + anon_request(url) def suite(): -- 2.11.4.GIT