0001-api-newsletters-retrieval-endpoint-10794.patch
corbo/api_urls.py | ||
---|---|---|
1 |
# corbo - Announces Manager |
|
2 |
# Copyright (C) 2016 Entr'ouvert |
|
3 |
# |
|
4 |
# This program is free software: you can redistribute it and/or modify it |
|
5 |
# under the terms of the GNU Affero General Public License as published |
|
6 |
# by the Free Software Foundation, either version 3 of the License, or |
|
7 |
# (at your option) any later version. |
|
8 |
# |
|
9 |
# This program is distributed in the hope that it will be useful, |
|
10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 |
# GNU Affero General Public License for more details. |
|
13 |
# |
|
14 |
# You should have received a copy of the GNU Affero General Public License |
|
15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | ||
17 |
from django.conf.urls import patterns, include, url |
|
18 | ||
19 |
from .api_views import NewslettersView |
|
20 | ||
21 |
urlpatterns = patterns('', |
|
22 |
url(r'^newsletters/', NewslettersView.as_view(), name='newsletters'), |
|
23 |
) |
corbo/api_views.py | ||
---|---|---|
1 |
# corbo - Announces Manager |
|
2 |
# Copyright (C) 2016 Entr'ouvert |
|
3 |
# |
|
4 |
# This program is free software: you can redistribute it and/or modify it |
|
5 |
# under the terms of the GNU Affero General Public License as published |
|
6 |
# by the Free Software Foundation, either version 3 of the License, or |
|
7 |
# (at your option) any later version. |
|
8 |
# |
|
9 |
# This program is distributed in the hope that it will be useful, |
|
10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 |
# GNU Affero General Public License for more details. |
|
13 |
# |
|
14 |
# You should have received a copy of the GNU Affero General Public License |
|
15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | ||
17 |
from rest_framework.views import APIView |
|
18 |
from rest_framework.response import Response |
|
19 | ||
20 |
from .models import Category, Subscription, channel_choices |
|
21 | ||
22 | ||
23 |
class NewslettersView(APIView): |
|
24 | ||
25 |
def get(self, request): |
|
26 |
newsletters = [] |
|
27 |
transports = [{'id': identifier, 'text': name} for identifier, name in channel_choices] |
|
28 |
for c in Category.objects.all(): |
|
29 |
newsletter = {'id': str(c.pk), 'text': c.name, |
|
30 |
'transports': transports} |
|
31 |
newsletters.append(newsletter) |
|
32 |
return Response({'data': newsletters}) |
corbo/channels.py | ||
---|---|---|
1 |
from django.utils.translation import ugettext_lazy as _ |
|
2 | ||
3 |
def get_channel_choices(include=[], exclude=[]): |
|
4 |
for channel in HomepageChannel, SMSChannel, EmailChannel: |
|
5 |
if include and channel.identifier not in include: |
|
6 |
continue |
|
7 |
if exclude and channel.identifier in exclude: |
|
8 |
continue |
|
9 |
for identifier, display_name in channel.get_choices(): |
|
10 |
yield (identifier, display_name) |
|
11 | ||
12 |
class HomepageChannel(object): |
|
13 |
identifier = 'homepage' |
|
14 | ||
15 |
@classmethod |
|
16 |
def get_choices(self): |
|
17 |
return (('homepage', _('Homepage')),) |
|
18 | ||
19 |
class SMSChannel(object): |
|
20 | ||
21 |
@classmethod |
|
22 |
def get_choices(self): |
|
23 |
return (('sms', _('SMS')),) |
|
24 | ||
25 |
def send(self, announce): |
|
26 |
pass |
|
27 | ||
28 |
class EmailChannel(object): |
|
29 |
identifier = 'email' |
|
30 | ||
31 |
@classmethod |
|
32 |
def get_choices(self): |
|
33 |
return (('email', _('Email')),) |
|
34 | ||
35 |
def send(self, announce): |
|
36 |
pass |
corbo/forms.py | ||
---|---|---|
1 | 1 |
from django import forms |
2 | 2 |
from django.utils.translation import ugettext_lazy as _ |
3 | 3 | |
4 |
from .models import Announce, Category, Broadcast |
|
5 |
from .channels import get_channel_choices |
|
4 |
from .models import Announce, Category, Broadcast, channel_choices
|
|
5 | ||
6 | 6 | |
7 | 7 |
class AnnounceForm(forms.ModelForm): |
8 | 8 |
transport_channel = forms.MultipleChoiceField(required=False, |
9 |
choices=get_channel_choices(),
|
|
9 |
choices=channel_choices,
|
|
10 | 10 |
widget=forms.CheckboxSelectMultiple()) |
11 | 11 | |
12 | 12 |
class Meta: |
corbo/models.py | ||
---|---|---|
5 | 5 | |
6 | 6 |
from ckeditor.fields import RichTextField |
7 | 7 | |
8 |
import channels |
|
8 |
channel_choices = ( |
|
9 |
('mailto', _('Email')), |
|
10 |
('homepage', _('Homepage')) |
|
11 |
) |
|
9 | 12 | |
10 | 13 |
class Category(models.Model): |
11 | 14 |
name = models.CharField(max_length=64, blank=False, null=False) |
... | ... | |
51 | 54 |
class Broadcast(models.Model): |
52 | 55 |
announce = models.ForeignKey(Announce, verbose_name=_('announce')) |
53 | 56 |
channel = models.CharField(_('channel'), max_length=32, |
54 |
choices=channels.get_channel_choices(), blank=False)
|
|
57 |
choices=channel_choices, blank=False)
|
|
55 | 58 |
time = models.DateTimeField(_('sent time'), auto_now_add=True) |
56 | 59 |
result = models.TextField(_('result'), blank=True) |
57 | 60 |
corbo/settings.py | ||
---|---|---|
41 | 41 |
'django.contrib.sessions', |
42 | 42 |
'django.contrib.messages', |
43 | 43 |
'django.contrib.staticfiles', |
44 |
'rest_framework', |
|
44 | 45 |
) |
45 | 46 | |
46 | 47 |
MIDDLEWARE_CLASSES = ( |
corbo/urls.py | ||
---|---|---|
8 | 8 |
from .views import homepage, atom |
9 | 9 | |
10 | 10 |
from manage_urls import urlpatterns as manage_urls |
11 |
from api_urls import urlpatterns as api_urls |
|
11 | 12 | |
12 | 13 |
urlpatterns = patterns('', |
13 | 14 |
url(r'^$', homepage, name='home'), |
... | ... | |
15 | 16 |
url(r'^manage/', decorated_includes(manager_required, |
16 | 17 |
include(manage_urls))), |
17 | 18 |
url(r'^ckeditor/', include('ckeditor.urls')), |
18 |
url(r'^admin/', include(admin.site.urls)) |
|
19 |
url(r'^admin/', include(admin.site.urls)), |
|
20 |
url(r'^api/', include(api_urls)) |
|
19 | 21 |
) |
20 | 22 | |
21 | 23 |
if 'mellon' in settings.INSTALLED_APPS: |
jenkins.sh | ||
---|---|---|
1 |
#!/bin/sh |
|
2 | ||
3 |
set -e |
|
4 | ||
5 |
rm -f coverage.xml |
|
6 |
rm -f test_results.xml |
|
7 | ||
8 |
pip install --upgrade tox |
|
9 |
pip install --upgrade pylint pylint-django |
|
10 |
tox -r |
|
11 |
test -f pylint.out && cp pylint.out pylint.out.prev |
|
12 |
(pylint -f parseable --rcfile /var/lib/jenkins/pylint.django.rc corbo/ | tee pylint.out) || /bin/true |
|
13 |
test -f pylint.out.prev && (diff pylint.out.prev pylint.out | grep '^[><]' | grep .py) || /bin/true |
requirements.txt | ||
---|---|---|
1 | 1 |
Django>=1.7, <1.8 |
2 | 2 |
django-ckeditor<4.5.3 |
3 |
djangorestframework |
|
3 | 4 |
-e git+http://repos.entrouvert.org/gadjo.git/#egg=gadjo |
setup.py | ||
---|---|---|
94 | 94 |
'Programming Language :: Python :: 2', |
95 | 95 |
], |
96 | 96 |
install_requires=['django>=1.7, <1.8', |
97 |
'django-ckeditor<4.5.3' |
|
97 |
'django-ckeditor<4.5.3', |
|
98 |
'djangorestframework', |
|
98 | 99 |
'gadjo' |
99 | 100 |
], |
100 | 101 |
zip_safe=False, |
tests/conftest.py | ||
---|---|---|
1 |
import pytest |
|
2 |
import django_webtest |
|
3 | ||
4 |
@pytest.fixture |
|
5 |
def app(request): |
|
6 |
wtm = django_webtest.WebTestMixin() |
|
7 |
wtm._patch_settings() |
|
8 |
request.addfinalizer(wtm._unpatch_settings) |
|
9 |
return django_webtest.DjangoTestApp() |
tests/test_api.py | ||
---|---|---|
1 |
import pytest |
|
2 |
import json |
|
3 | ||
4 | ||
5 |
from django.core.urlresolvers import reverse |
|
6 | ||
7 |
from corbo.models import Category, Announce, Broadcast |
|
8 | ||
9 |
pytestmark = pytest.mark.django_db |
|
10 | ||
11 |
CATEGORIES = ('Alerts', 'News') |
|
12 | ||
13 | ||
14 |
@pytest.fixture |
|
15 |
def categories(): |
|
16 |
categories = [] |
|
17 |
for category in CATEGORIES: |
|
18 |
c, created = Category.objects.get_or_create(name=category) |
|
19 |
categories.append(c) |
|
20 |
return categories |
|
21 | ||
22 |
@pytest.fixture |
|
23 |
def announces(): |
|
24 |
announces = [] |
|
25 |
for category in Category.objects.all(): |
|
26 |
a = Announce.objects.create(category=category, title='By email') |
|
27 |
Broadcast.objects.create(announce=a, channel='mailto') |
|
28 |
announces.append(a) |
|
29 |
a = Announce.objects.create(category=category, title='On homepage') |
|
30 |
Broadcast.objects.create(announce=a, channel='homepage') |
|
31 |
announces.append(a) |
|
32 |
return announces |
|
33 | ||
34 | ||
35 |
def test_get_newsletters(app, categories, announces): |
|
36 |
resp = app.get(reverse('newsletters'), status=200) |
|
37 |
data = resp.json |
|
38 |
assert data['data'] |
|
39 |
for category in data['data']: |
|
40 |
assert 'id' in category |
|
41 |
assert 'text' in category |
|
42 |
assert category['text'] in CATEGORIES |
|
43 |
assert 'transports' in category |
|
44 |
assert category['transports'] == [{'id': 'mailto', 'text': 'Email'}, |
|
45 |
{'id': 'homepage', 'text': 'Homepage'} |
|
46 |
] |
tox.ini | ||
---|---|---|
1 |
[tox] |
|
2 |
envlist = coverage-{django17,django18} |
|
3 | ||
4 |
[testenv] |
|
5 |
usedevelop = |
|
6 |
coverage: True |
|
7 |
setenv = |
|
8 |
DJANGO_SETTINGS_MODULE=corbo.settings |
|
9 |
coverage: COVERAGE=--junitxml=test_results.xml --cov-report xml --cov=corbo/ --cov-config .coveragerc |
|
10 |
deps = |
|
11 |
django17: django>1.7,<1.8 |
|
12 |
django18: django>=1.8,<1.9 |
|
13 |
pytest-cov |
|
14 |
pytest-django |
|
15 |
pytest |
|
16 |
pytest-capturelog |
|
17 |
django-webtest |
|
18 |
django-ckeditor<4.5.3 |
|
19 |
djangorestframework |
|
20 |
pylint==1.4.0 |
|
21 |
astroid==1.3.2 |
|
22 |
commands = |
|
23 |
py.test {env:COVERAGE:} {posargs:tests/} |
|
0 |
- |