Projet

Général

Profil

0001-api-newsletters-retrieval-endpoint-10794.patch

Voir les différences:

Subject: [PATCH 1/3] api: newsletters retrieval endpoint (#10794)

 corbo/api_urls.py  | 23 +++++++++++++++++++++++
 corbo/api_views.py | 32 ++++++++++++++++++++++++++++++++
 corbo/channels.py  | 36 ------------------------------------
 corbo/forms.py     |  6 +++---
 corbo/models.py    |  7 +++++--
 corbo/settings.py  |  1 +
 corbo/urls.py      |  4 +++-
 jenkins.sh         | 13 +++++++++++++
 requirements.txt   |  1 +
 setup.py           |  3 ++-
 tests/conftest.py  |  9 +++++++++
 tests/test_api.py  | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 tox.ini            | 23 +++++++++++++++++++++++
 13 files changed, 161 insertions(+), 43 deletions(-)
 create mode 100644 corbo/api_urls.py
 create mode 100644 corbo/api_views.py
 delete mode 100644 corbo/channels.py
 create mode 100755 jenkins.sh
 create mode 100644 tests/conftest.py
 create mode 100644 tests/test_api.py
 create mode 100644 tox.ini
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
-