Skip to content

Commit

Permalink
Merge branch 'master' into oauth-login
Browse files Browse the repository at this point in the history
  • Loading branch information
stefankoegl committed Jul 4, 2017
2 parents 69010d6 + 5cd52a5 commit 2e4a931
Show file tree
Hide file tree
Showing 24 changed files with 235 additions and 148 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
language: python

python:
- "3.4"
- "3.5"
- "nightly"

services:
- redis-server
Expand Down
8 changes: 6 additions & 2 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ test:
coverage report

clean:
find -name "*.pyc" -exec rm '{}' \;
git clean -fX

install-deps:
sudo apt-get install libpq-dev libjpeg-dev zlib1g-dev libwebp-dev \
build-essential python3-dev virtualenv

.PHONY: all help test clean unittest coverage

.PHONY: all help test clean unittest coverage install-deps

27 changes: 19 additions & 8 deletions mygpo/api/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,14 @@

import uuid

from django.db import transaction, IntegrityError

from mygpo.users.settings import STORE_UA
from mygpo.users.models import Client

import logging
logger = logging.getLogger(__name__)


def get_device(user, uid, user_agent, undelete=True):
"""
Expand All @@ -30,21 +35,27 @@ def get_device(user, uid, user_agent, undelete=True):

store_ua = user.profile.settings.get_wksetting(STORE_UA)

save = False
# list of fields to update -- empty list = no update
update_fields = []

with transaction.atomic():
try:
client = Client(id=uuid.uuid1(), user=user, uid=uid)
client.full_clean()
client.save()

client, created = Client.objects.get_or_create(user=user, uid=uid,
defaults = {
'id': uuid.uuid1()
})
except IntegrityError:
client = Client.objects.get(user=user, uid=uid)

if client.deleted and undelete:
client.deleted = False
save = True
update_fields.append('deleted')

if store_ua and user_agent and client.user_agent != user_agent:
client.user_agent = user_agent
update_fields.append('user_agent')

if save:
client.save()
if update_fields:
client.save(update_fields=update_fields)

return client
33 changes: 24 additions & 9 deletions mygpo/api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@


import json
import copy
import unittest
import doctest
from urllib.parse import urlencode
from copy import deepcopy

from django.test.client import Client
from django.test import TestCase
Expand Down Expand Up @@ -71,23 +70,39 @@ def tearDown(self):
self.user.delete()

def test_episode_actions(self):
response = self._upload_episode_actions(self.user, self.action_data,
self.extra)
self.assertEqual(response.status_code, 200, response.content)

url = reverse(episodes, kwargs={
'version': '2',
'username': self.user.username,
})

# upload actions
response = self.client.post(url, json.dumps(self.action_data),
content_type="application/json",
**self.extra)
self.assertEqual(response.status_code, 200, response.content)

response = self.client.get(url, {'since': '0'}, **self.extra)
self.assertEqual(response.status_code, 200, response.content)
response_obj = json.loads(response.content.decode('utf-8'))
actions = response_obj['actions']
self.assertTrue(self.compare_action_list(self.action_data, actions))

def test_invalid_client_id(self):
""" Invalid Client ID should return 400 """
action_data = copy.deepcopy(self.action_data)
action_data[0]['device'] = "gpodder@abcdef123"

response = self._upload_episode_actions(self.user, action_data,
self.extra)

self.assertEqual(response.status_code, 400, response.content)

def _upload_episode_actions(self, user, action_data, extra):
url = reverse(episodes, kwargs={
'version': '2',
'username': self.user.username,
})
return self.client.post(url, json.dumps(action_data),
content_type="application/json",
**extra)

def compare_action_list(self, as1, as2):
for a1 in as1:
found = False
Expand Down
59 changes: 13 additions & 46 deletions mygpo/core/slugs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,6 @@

from django.utils.text import slugify

from mygpo.podcasts.models import Slug, Episode


# TODO: move to feed-downloader?
def assign_missing_episode_slugs(podcast):
common_title = podcast.get_common_episode_title()

episodes = Episode.objects.filter(podcast=podcast, slugs__isnull=True)

for episode in episodes:
try:
slug = EpisodeSlug(episode, common_title).get_slug()
except ValueError:
return

if slug:
episode.set_slug(slug)


class SlugGenerator(object):
""" Generates a unique slug for an object """
Expand All @@ -39,45 +21,32 @@ def _get_base_slug(obj):
base_slug = slugify(obj.title)
return base_slug

def __iter__(self):
""" Generates possible slugs
@staticmethod
def _get_existing_slugs():
return []

The consumer can can consume until it get's an unused one """

def get_slug(self):
""" Gets existing slugs and appends numbers until slug is unique """
if not self.base_slug:
return None
raise StopIteration

existing_slugs = self._get_existing_slugs()

if not self.base_slug in existing_slugs:
return str(self.base_slug)
# first we try with the base slug
yield str(self.base_slug)

for n in count(1):
tmp_slug = '%s-%d' % (self.base_slug, n)
if not tmp_slug in existing_slugs:
# slugify returns SafeUnicode, we need a plain string
return str(tmp_slug)

def _get_existing_slugs(self):
query = Slug.objects.filter(scope=self.obj.scope,
slug__startswith=self.base_slug)
return [s.slug for s in query]
# slugify returns SafeUnicode, we need a plain string
yield str(tmp_slug)


class PodcastGroupSlug(SlugGenerator):
class PodcastGroupSlugs(SlugGenerator):
""" Generates slugs for Podcast Groups """

pass


class PodcastSlug(PodcastGroupSlug):
class PodcastSlugs(PodcastGroupSlugs):
""" Generates slugs for Podcasts """

@staticmethod
def _get_base_slug(podcast):
def _get_base_slug(self, podcast):
base_slug = SlugGenerator._get_base_slug(podcast)

if not base_slug:
Expand All @@ -92,16 +61,14 @@ def _get_base_slug(podcast):
return base_slug


class EpisodeSlug(SlugGenerator):
class EpisodeSlugs(SlugGenerator):
""" Generates slugs for Episodes """

def __init__(self, episode, common_title):
self.common_title = common_title
super(EpisodeSlug, self).__init__(episode)
self.podcast_id = episode.podcast
super().__init__(episode)

def _get_base_slug(self, obj):

number = obj.get_episode_number(self.common_title)
if number:
return str(number)
Expand Down
41 changes: 34 additions & 7 deletions mygpo/data/feeddownloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
from django.db import transaction
from django.conf import settings

from mygpo.podcasts.models import Podcast, URL, Slug, Episode
from mygpo.core.slugs import assign_missing_episode_slugs, PodcastSlug
from mygpo.podcasts.models import Podcast, Episode
from mygpo.core.slugs import PodcastSlugs, EpisodeSlugs
from mygpo.podcasts.models import DEFAULT_UPDATE_INTERVAL, \
MIN_UPDATE_INTERVAL, MAX_UPDATE_INTERVAL
from mygpo.utils import file_hash, to_maxlength
Expand Down Expand Up @@ -240,15 +240,42 @@ def _update_podcast(podcast, parsed, episodes, max_episode_order):
except SubscriptionError as se:
logger.warn('subscribing to hub failed: %s', str(se))

if not podcast.slug:
slug = PodcastSlug(podcast).get_slug()
if slug:
podcast.add_slug(slug)

assign_slug(podcast)
assign_missing_episode_slugs(podcast)
update_related_podcasts.delay(podcast)


def assign_slug(podcast):
if podcast.slug:
return

for slug in PodcastSlugs(podcast):
try:
with transaction.atomic():
podcast.add_slug(slug)
break

except:
continue


def assign_missing_episode_slugs(podcast):
common_title = podcast.get_common_episode_title()

episodes = Episode.objects.filter(podcast=podcast, slugs__isnull=True)

for episode in episodes:

for slug in EpisodeSlugs(episode, common_title):
try:
with transaction.atomic():
episode.set_slug(slug)
break

except:
continue


def _update_categories(podcast, prev_timestamp):
""" checks some practical requirements and updates a category """

Expand Down
6 changes: 3 additions & 3 deletions mygpo/directory/tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ def update_category(podcast):
if not all_tags:
return

random_tag = choice(all_tags)
random_tag = choice(all_tags).strip()

try:
category, created = Category.objects.get_or_create(
tags__tag=slugify(random_tag.strip()),
tags__tag=slugify(random_tag),
defaults={
'title': random_tag.strip(),
'title': random_tag,
}
)

Expand Down
5 changes: 2 additions & 3 deletions mygpo/podcastlists/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from django.db import models, migrations
import django.db.models.deletion
from django.conf import settings
import uuidfield.fields


class Migration(migrations.Migration):
Expand All @@ -18,7 +17,7 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='PodcastList',
fields=[
('id', uuidfield.fields.UUIDField(max_length=32, serialize=False, primary_key=True)),
('id', models.UUIDField(max_length=32, serialize=False, primary_key=True)),
('title', models.CharField(max_length=512)),
('slug', models.SlugField(max_length=128)),
('created', models.DateTimeField()),
Expand All @@ -36,7 +35,7 @@ class Migration(migrations.Migration):
('created', models.DateTimeField(auto_now_add=True)),
('modified', models.DateTimeField(auto_now=True)),
('order', models.PositiveSmallIntegerField()),
('object_id', uuidfield.fields.UUIDField(max_length=32)),
('object_id', models.UUIDField(max_length=32)),
('content_type', models.ForeignKey(to='contenttypes.ContentType', on_delete=django.db.models.deletion.PROTECT)),
('podcastlist', models.ForeignKey(related_name='entries', to='podcastlists.PodcastList')),
],
Expand Down
Loading

0 comments on commit 2e4a931

Please sign in to comment.