0001-add-support-of-Django-1.11-19614.patch
corbo/api_urls.py | ||
---|---|---|
14 | 14 |
# You should have received a copy of the GNU Affero General Public License |
15 | 15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | 16 | |
17 |
from django.conf.urls import patterns, url
|
|
17 |
from django.conf.urls import url |
|
18 | 18 | |
19 | 19 |
from .api_views import NewslettersView, SubscriptionsView, SubscribeView |
20 | 20 | |
21 | 21 | |
22 |
urlpatterns = patterns('',
|
|
22 |
urlpatterns = [
|
|
23 | 23 |
url(r'^newsletters/', NewslettersView.as_view(), name='newsletters'), |
24 | 24 |
url(r'^subscriptions/', SubscriptionsView.as_view(), name='subscriptions'), |
25 | 25 |
url(r'^subscribe/', SubscribeView.as_view(), name='subscribe'), |
26 |
) |
|
26 |
] |
corbo/manage_urls.py | ||
---|---|---|
1 |
from django.conf.urls import patterns, include, url
|
|
1 |
from django.conf.urls import url |
|
2 | 2 | |
3 | 3 |
from .views import add_announce, edit_announce, delete_announce, \ |
4 | 4 |
add_category, edit_category, view_category, delete_category, manage, \ |
5 | 5 |
subscriptions_import, view_announce, email_announce, sms_announce, \ |
6 | 6 |
menu_json |
7 | 7 | |
8 |
urlpatterns = patterns('',
|
|
8 |
urlpatterns = [
|
|
9 | 9 |
url(r'^$', manage, name='manage'), |
10 | 10 |
url(r'^category/(?P<slug>[\w-]+)/announce/$', add_announce, |
11 | 11 |
name='add_announce'), |
... | ... | |
30 | 30 |
url(r'^category/(?P<slug>[\w-]+)/import-subscriptions/$', subscriptions_import, |
31 | 31 |
name='subscriptions-import'), |
32 | 32 |
url(r'^menu.json$', menu_json), |
33 |
) |
|
33 |
] |
corbo/settings.py | ||
---|---|---|
54 | 54 |
'django.middleware.clickjacking.XFrameOptionsMiddleware', |
55 | 55 |
) |
56 | 56 | |
57 |
# Templates |
|
58 |
TEMPLATES = [ |
|
59 |
{ |
|
60 |
'BACKEND': 'django.template.backends.django.DjangoTemplates', |
|
61 |
'DIRS': [ |
|
62 |
], |
|
63 |
'APP_DIRS': True, |
|
64 |
'OPTIONS': { |
|
65 |
'context_processors': [ |
|
66 |
'django.contrib.auth.context_processors.auth', |
|
67 |
'django.template.context_processors.debug', |
|
68 |
'django.template.context_processors.i18n', |
|
69 |
'django.template.context_processors.media', |
|
70 |
'django.template.context_processors.static', |
|
71 |
'django.template.context_processors.tz', |
|
72 |
'django.contrib.messages.context_processors.messages', |
|
73 |
'django.template.context_processors.request' |
|
74 |
], |
|
75 |
}, |
|
76 |
}, |
|
77 |
] |
|
78 | ||
57 | 79 |
ROOT_URLCONF = 'corbo.urls' |
58 | 80 | |
59 | 81 |
WSGI_APPLICATION = 'corbo.wsgi.application' |
... | ... | |
82 | 104 | |
83 | 105 |
USE_TZ = True |
84 | 106 | |
85 |
STATICFILES_FINDERS = global_settings.STATICFILES_FINDERS + ('gadjo.finders.XStaticFinder',)
|
|
107 |
STATICFILES_FINDERS = tuple(global_settings.STATICFILES_FINDERS) + ('gadjo.finders.XStaticFinder',)
|
|
86 | 108 | |
87 |
if not 'django.template.context_processors.request' in global_settings.TEMPLATE_CONTEXT_PROCESSORS: |
|
88 |
TEMPLATE_CONTEXT_PROCESSORS = ('django.template.context_processors.request',) + \ |
|
89 |
global_settings.TEMPLATE_CONTEXT_PROCESSORS |
|
109 |
# compatibility with django<1.10 |
|
110 |
if hasattr(global_settings, 'TEMPLATE_CONTEXT_PROCESSORS'): |
|
111 |
if not 'django.template.context_processors.request' in global_settings.TEMPLATE_CONTEXT_PROCESSORS: |
|
112 |
TEMPLATE_CONTEXT_PROCESSORS = ('django.template.context_processors.request',) + \ |
|
113 |
global_settings.TEMPLATE_CONTEXT_PROCESSORS |
|
90 | 114 | |
91 | 115 | |
92 | 116 |
# Static files (CSS, JavaScript, Images) |
corbo/urls.py | ||
---|---|---|
1 | 1 |
from django.conf import settings |
2 |
from django.conf.urls import patterns, include, url
|
|
2 |
from django.conf.urls import include, url |
|
3 | 3 |
from django.conf.urls.static import static |
4 | 4 |
from django.contrib.staticfiles.urls import staticfiles_urlpatterns |
5 | 5 |
from django.contrib import admin |
... | ... | |
15 | 15 | |
16 | 16 |
import ckeditor.views as ckeditor_views |
17 | 17 | |
18 |
urlpatterns = patterns('', |
|
18 | ||
19 |
urlpatterns = [ |
|
19 | 20 |
url(r'^$', homepage, name='home'), |
20 | 21 |
url(r'^atom$', atom, name='atom'), |
21 | 22 |
url(r'^manage/', decorated_includes(manager_required, |
... | ... | |
32 | 33 |
name='ckeditor_upload'), |
33 | 34 |
url(r'^ckeditor/browse/', never_cache(staff_member_required(ckeditor_views.browse)), |
34 | 35 |
name='ckeditor_browse'), |
35 |
) |
|
36 |
] |
|
36 | 37 | |
37 | 38 |
if 'mellon' in settings.INSTALLED_APPS: |
38 |
urlpatterns += patterns('', url(r'^accounts/mellon/', include('mellon.urls')))
|
|
39 |
urlpatterns.append(url(r'^accounts/mellon/', include('mellon.urls')))
|
|
39 | 40 | |
40 | 41 |
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) |
41 | 42 |
urlpatterns += staticfiles_urlpatterns() |
corbo/utils.py | ||
---|---|---|
24 | 24 |
from lxml import etree |
25 | 25 | |
26 | 26 |
from django.conf import settings |
27 |
from django.template import loader, Context
|
|
27 |
from django.template import loader |
|
28 | 28 |
from django.utils.translation import activate |
29 | 29 |
from django.core.files.storage import DefaultStorage |
30 | 30 |
from django.core.urlresolvers import reverse |
... | ... | |
45 | 45 |
template = loader.get_template('corbo/announce.html') |
46 | 46 |
message = Message(subject=title, mail_from=settings.DEFAULT_FROM_EMAIL, |
47 | 47 |
html=template.render( |
48 |
Context({'content': content, |
|
49 |
'unsubscribe_link_placeholder': UNSUBSCRIBE_LINK_PLACEHOLDER}))) |
|
48 |
{'content': content, 'unsubscribe_link_placeholder': UNSUBSCRIBE_LINK_PLACEHOLDER})) |
|
50 | 49 | |
51 | 50 |
# perform transformations in message html, like inline css parsing |
52 | 51 |
message.transformer.apply_to_images(func=transform_image_src) |
corbo/views.py | ||
---|---|---|
51 | 51 | |
52 | 52 |
class HomepageView(RedirectView): |
53 | 53 |
pattern_name = 'manage' |
54 |
permanent = True |
|
54 | 55 | |
55 | 56 | |
56 | 57 |
homepage = HomepageView.as_view() |
... | ... | |
71 | 72 | |
72 | 73 |
def get_context_data(self, **kwargs): |
73 | 74 |
context = super(AnnounceCreateView, self).get_context_data(**kwargs) |
74 |
context['category'] = kwargs['form'].initial['category']
|
|
75 |
context['category'] = context['form'].initial['category']
|
|
75 | 76 |
return context |
76 | 77 | |
77 | 78 | |
... | ... | |
84 | 85 | |
85 | 86 |
def get_context_data(self, **kwargs): |
86 | 87 |
context = super(AnnounceEditView, self).get_context_data(**kwargs) |
87 |
category_id = kwargs['form'].initial['category']
|
|
88 |
category_id = context['form'].initial['category']
|
|
88 | 89 |
context['category'] = models.Category.objects.get(pk=category_id) |
89 | 90 |
return context |
90 | 91 |
requirements.txt | ||
---|---|---|
1 |
Django>1.7, <1.9
|
|
1 |
Django>1.7, <1.12
|
|
2 | 2 |
django-ckeditor<4.5.3 |
3 | 3 |
djangorestframework>=3.3,<3.4 |
4 | 4 |
html2text |
setup.py | ||
---|---|---|
93 | 93 |
'Programming Language :: Python', |
94 | 94 |
'Programming Language :: Python :: 2', |
95 | 95 |
], |
96 |
install_requires=['django>1.7, <1.9',
|
|
96 |
install_requires=['django>1.7, <1.12',
|
|
97 | 97 |
'django-ckeditor<4.5.3', |
98 | 98 |
'djangorestframework>=3.3,<3.4', |
99 | 99 |
'html2text', |
tests/test_manager.py | ||
---|---|---|
20 | 20 |
return user |
21 | 21 | |
22 | 22 |
def login(app, username='admin', password='admin'): |
23 |
login_page = app.get('/login/')
|
|
23 |
login_page = app.get(reverse('auth_login'))
|
|
24 | 24 |
login_form = login_page.forms[0] |
25 | 25 |
login_form['username'] = username |
26 | 26 |
login_form['password'] = password |
... | ... | |
30 | 30 | |
31 | 31 |
def test_unlogged_access(app): |
32 | 32 |
# connect while not being logged in |
33 |
assert app.get('/', status=301).location == 'http://testserver/manage/'
|
|
34 |
assert app.get('/manage/', status=302).location == 'http://testserver/login/?next=/manage/'
|
|
33 |
assert app.get('/', status=301).location.endswith(reverse('manage'))
|
|
34 |
assert app.get('/manage/', status=302).location.endswith(reverse('auth_login') + '?next=/manage/')
|
|
35 | 35 | |
36 | 36 |
def test_access(app, admin_user): |
37 | 37 |
app = login(app) |
38 |
resp = app.get('/manage/', status=200)
|
|
38 |
resp = app.get(reverse('manage'), status=200)
|
|
39 | 39 |
assert 'New category' in resp.body |
40 | 40 | |
41 | 41 |
def test_logout(app, admin_user): |
42 | 42 |
app = login(app) |
43 |
app.get('/logout/')
|
|
44 |
assert app.get('/', status=301).location == 'http://testserver/manage/'
|
|
43 |
app.get(reverse('auth_logout'))
|
|
44 |
assert app.get('/', status=301).location.endswith(reverse('manage'))
|
|
45 | 45 | |
46 | 46 |
def test_create_category(app, admin_user): |
47 | 47 |
app = login(app) |
... | ... | |
52 | 52 |
category_form['name'] = 'Alerts' |
53 | 53 |
resp = category_form.submit() |
54 | 54 |
assert resp.status_int == 302 |
55 |
assert resp.location == 'http://testserver/manage/'
|
|
56 |
resp = app.get('http://testserver/manage/')
|
|
55 |
assert resp.location.endswith(reverse('manage'))
|
|
56 |
resp = resp.follow()
|
|
57 | 57 |
assert 'Alerts' in resp.content |
58 | 58 | |
59 | 59 |
def test_edit_category(app, admin_user): |
60 | 60 |
app = login(app) |
61 |
resp = app.get('/manage/')
|
|
61 |
resp = app.get(reverse('manage'))
|
|
62 | 62 |
assert 'New category' in resp.content |
63 | 63 |
category_page = resp.click('New category') |
64 | 64 |
category_form = category_page.forms[0] |
65 | 65 |
category_form['name'] = 'Alerts' |
66 | 66 |
resp = category_form.submit() |
67 | 67 |
assert resp.status_int == 302 |
68 |
assert resp.location == 'http://testserver/manage/'
|
|
69 |
resp = app.get('http://testserver/manage/')
|
|
68 |
assert resp.location.endswith(reverse('manage'))
|
|
69 |
resp = app.get(reverse('manage'))
|
|
70 | 70 |
assert 'Alerts' in resp.content |
71 | 71 |
assert '0 announces' in resp.content |
72 | 72 |
assert '0 subscriptions' in resp.content |
... | ... | |
77 | 77 |
edit_form['name'] = 'New Alerts' |
78 | 78 |
resp = edit_form.submit() |
79 | 79 |
assert resp.status_int == 302 |
80 |
assert resp.location == 'http://testserver/manage/category/alerts/'
|
|
80 |
assert resp.location.endswith(reverse('view_category', kwargs={'slug': 'alerts'}))
|
|
81 | 81 | |
82 | 82 |
def test_delete_category(app, admin_user): |
83 | 83 |
app = login(app) |
84 |
resp = app.get('/manage/')
|
|
84 |
resp = app.get(reverse('manage'))
|
|
85 | 85 |
assert 'New category' in resp.content |
86 | 86 |
category_page = resp.click('New category') |
87 | 87 |
category_form = category_page.forms[0] |
88 | 88 |
category_form['name'] = 'Alerts' |
89 | 89 |
resp = category_form.submit() |
90 | 90 |
assert resp.status_int == 302 |
91 |
assert resp.location == 'http://testserver/manage/'
|
|
92 |
resp = app.get('http://testserver/manage/')
|
|
91 |
assert resp.location.endswith(reverse('manage'))
|
|
92 |
resp = app.get(reverse('manage'))
|
|
93 | 93 |
assert 'Alerts' in resp.content |
94 | 94 |
assert '0 announces' in resp.content |
95 | 95 |
assert '0 subscriptions' in resp.content |
... | ... | |
99 | 99 |
delete_form = delete_page.forms[0] |
100 | 100 |
resp = delete_form.submit() |
101 | 101 |
assert resp.status_int == 302 |
102 |
assert resp.location == 'http://testserver/manage/'
|
|
102 |
assert resp.location.endswith(reverse('manage'))
|
|
103 | 103 | |
104 | 104 |
def test_create_announce(app, admin_user): |
105 | 105 |
app = login(app) |
... | ... | |
110 | 110 |
category_form['name'] = 'Alerts' |
111 | 111 |
resp = category_form.submit() |
112 | 112 |
assert resp.status_int == 302 |
113 |
assert resp.location == 'http://testserver/manage/'
|
|
114 |
resp = app.get('http://testserver/manage/')
|
|
113 |
assert resp.location.endswith(reverse('manage'))
|
|
114 |
resp = app.get(reverse('manage'))
|
|
115 | 115 |
assert 'Alerts' in resp.content |
116 | 116 |
resp = resp.click('Alerts') |
117 | 117 |
assert 'New announce' in resp.content |
... | ... | |
121 | 121 |
announce_form['text'] = 'announce content' |
122 | 122 |
resp = announce_form.submit() |
123 | 123 |
assert resp.status_int == 302 |
124 |
assert resp.location == 'http://testserver/manage/category/alerts/' |
|
125 |
resp = app.get('http://testserver/manage/category/alerts/') |
|
124 |
category_url = reverse('view_category', kwargs={'slug': 'alerts'}) |
|
125 |
assert resp.location.endswith(category_url) |
|
126 |
resp = resp.follow() |
|
126 | 127 |
assert 'First announce' in resp.content |
127 | 128 | |
128 | 129 |
def test_edit_announce(app, admin_user): |
... | ... | |
134 | 135 |
category_form['name'] = 'Alerts' |
135 | 136 |
resp = category_form.submit() |
136 | 137 |
assert resp.status_int == 302 |
137 |
assert resp.location == 'http://testserver/manage/'
|
|
138 |
assert resp.location.endswith(reverse('manage'))
|
|
138 | 139 |
resp = app.get(resp.location) |
139 | 140 |
resp = resp.click('Alerts') |
140 | 141 |
assert 'New announce' in resp.content |
... | ... | |
144 | 145 |
announce_form['text'] = 'announce content' |
145 | 146 |
resp = announce_form.submit() |
146 | 147 |
assert resp.status_int == 302 |
147 |
assert resp.location == 'http://testserver/manage/category/alerts/'
|
|
148 |
resp = app.get(resp.location)
|
|
148 |
assert resp.location.endswith(reverse('view_category', kwargs={'slug': 'alerts'}))
|
|
149 |
resp = resp.follow()
|
|
149 | 150 |
assert 'First announce' in resp.content |
150 | 151 |
announce_page = resp.click('First announce') |
151 | 152 |
assert 'First announce' in announce_page.content |
... | ... | |
158 | 159 |
edit_form['expiration_time'] = '2017-12-31 23:00:00' |
159 | 160 |
resp = edit_form.submit() |
160 | 161 |
assert resp.status_int == 302 |
161 |
assert resp.location == 'http://testserver/manage/announce/1/'
|
|
162 |
assert resp.location.endswith(reverse('view_announce', kwargs={'pk': 1}))
|
|
162 | 163 | |
163 | 164 |
# simulate announce deliver |
164 | 165 |
broadcast = Broadcast.objects.get(announce__pk=1) |
... | ... | |
190 | 191 |
category_form['name'] = 'Alerts' |
191 | 192 |
resp = category_form.submit() |
192 | 193 |
assert resp.status_int == 302 |
193 |
assert resp.location == 'http://testserver/manage/'
|
|
194 |
resp = app.get('http://testserver/manage/')
|
|
194 |
assert resp.location.endswith(reverse('manage'))
|
|
195 |
resp = app.get(reverse('manage'))
|
|
195 | 196 |
resp = resp.click('Alerts') |
196 | 197 |
assert 'New announce' in resp.content |
197 | 198 |
announce_page = resp.click('New announce') |
... | ... | |
200 | 201 |
announce_form['text'] = 'announce content' |
201 | 202 |
resp = announce_form.submit() |
202 | 203 |
assert resp.status_int == 302 |
203 |
assert resp.location == 'http://testserver/manage/category/alerts/'
|
|
204 |
resp = app.get('http://testserver/manage/category/alerts/')
|
|
204 |
assert resp.location.endswith(reverse('view_category', kwargs={'slug': 'alerts'}))
|
|
205 |
resp = resp.follow()
|
|
205 | 206 |
assert 'First announce' in resp.content |
206 | 207 |
resp = resp.click('First announce') |
207 | 208 |
assert 'Delete' in resp.content |
... | ... | |
210 | 211 |
announce_delete_form = announce_delete_page.forms[0] |
211 | 212 |
resp = announce_delete_form.submit() |
212 | 213 |
assert resp.status_int == 302 |
213 |
assert resp.location == 'http://testserver/manage/category/alerts/'
|
|
214 |
assert resp.location.endswith(reverse('view_category', kwargs={'slug': 'alerts'}))
|
|
214 | 215 | |
215 | 216 |
def test_email_announce(app, admin_user): |
216 | 217 |
app = login(app) |
... | ... | |
221 | 222 |
category_form['name'] = 'Alerts' |
222 | 223 |
resp = category_form.submit() |
223 | 224 |
assert resp.status_int == 302 |
224 |
assert resp.location == 'http://testserver/manage/'
|
|
225 |
resp = app.get('http://testserver/manage/')
|
|
225 |
assert resp.location.endswith(reverse('manage'))
|
|
226 |
resp = resp.follow()
|
|
226 | 227 |
resp = resp.click('Alerts') |
227 | 228 |
assert 'New announce' in resp.content |
228 | 229 |
announce_page = resp.click('New announce') |
... | ... | |
231 | 232 |
announce_form['text'] = 'announce content' |
232 | 233 |
resp = announce_form.submit() |
233 | 234 |
assert resp.status_int == 302 |
234 |
assert resp.location == 'http://testserver/manage/category/alerts/'
|
|
235 |
resp = app.get(resp.location)
|
|
235 |
assert resp.location.endswith(reverse('view_category', kwargs={'slug': 'alerts'}))
|
|
236 |
resp = resp.follow()
|
|
236 | 237 |
assert 'First announce' in resp.content |
237 | 238 |
resp = resp.click('First announce') |
238 | 239 |
assert 'Send test email' in resp.content |
... | ... | |
246 | 247 |
assert 'Cancel' in resp.content |
247 | 248 |
resp = send_form.submit() |
248 | 249 |
assert resp.status_int == 302 |
249 |
assert resp.location == 'http://testserver/manage/announce/1/'
|
|
250 |
assert resp.location.endswith(reverse('view_announce', kwargs={'pk': '1'}))
|
|
250 | 251 | |
251 | 252 |
@mock.patch('corbo.utils.requests.post') |
252 | 253 |
def test_sms_announce(mocked_post, app, admin_user, settings): |
... | ... | |
326 | 327 |
announce_form['text'] = 'announce content' |
327 | 328 |
resp = announce_form.submit() |
328 | 329 |
assert resp.status_int == 302 |
329 |
assert resp.location == 'http://testserver/manage/category/alerts/'
|
|
330 |
assert resp.location.endswith(reverse('view_category', kwargs={'slug': 'alerts'}))
|
|
330 | 331 |
resp = resp.follow() |
331 | 332 |
assert 'First announce' in resp.content |
332 | 333 |
settings.SMS_GATEWAY_URL='invalid_url' |
tests/test_subscribers.py | ||
---|---|---|
1 | 1 |
import pytest |
2 |
from webtest import TestApp, Upload
|
|
2 |
from webtest import Upload |
|
3 | 3 | |
4 |
from django.core.wsgi import get_wsgi_application |
|
5 | 4 |
from django.utils.text import slugify |
6 | 5 |
from django.core.urlresolvers import reverse |
7 | 6 |
from django.contrib.auth import get_user_model |
... | ... | |
42 | 41 |
assert resp.status_int == 302 |
43 | 42 |
return app |
44 | 43 | |
45 |
def test_subscribe_from_csv(admin, categories): |
|
46 |
app = login(TestApp(get_wsgi_application()))
|
|
44 |
def test_subscribe_from_csv(app, admin, categories):
|
|
45 |
app = login(app)
|
|
47 | 46 |
for c in categories: |
48 | 47 |
page = app.get(reverse('subscriptions-import', kwargs={'slug': c.slug})) |
49 | 48 |
form = page.form |
... | ... | |
52 | 51 |
assert res.status_code == 302 |
53 | 52 |
assert Subscription.objects.filter(category=c).count() == len(CSV_CONTENT.splitlines()) |
54 | 53 | |
55 |
def test_subscribe_from_csv_with_empty_lines(admin, categories): |
|
56 |
app = login(TestApp(get_wsgi_application()))
|
|
54 |
def test_subscribe_from_csv_with_empty_lines(app, admin, categories):
|
|
55 |
app = login(app)
|
|
57 | 56 |
content = CSV_CONTENT + '\n\n\n' |
58 | 57 |
for c in categories: |
59 | 58 |
page = app.get(reverse('subscriptions-import', kwargs={'slug': c.slug})) |
... | ... | |
63 | 62 |
assert res.status_code == 302 |
64 | 63 |
assert Subscription.objects.filter(category=c).count() == len(CSV_CONTENT.splitlines()) |
65 | 64 | |
66 |
def test_subscribe_with_invalid_email(admin, categories): |
|
67 |
app = login(TestApp(get_wsgi_application()))
|
|
65 |
def test_subscribe_with_invalid_email(app, admin, categories):
|
|
66 |
app = login(app)
|
|
68 | 67 |
content = CSV_CONTENT + '\nwrong, Wrong user,' |
69 | 68 |
for category in categories: |
70 | 69 |
page = app.get(reverse('subscriptions-import', kwargs={'slug': category.slug})) |
tox.ini | ||
---|---|---|
1 | 1 |
[tox] |
2 |
envlist = coverage-django18 |
|
2 |
envlist = coverage-django18,coverage-django111
|
|
3 | 3 | |
4 | 4 |
[testenv] |
5 | 5 |
usedevelop = |
... | ... | |
10 | 10 |
coverage: COVERAGE=--junitxml=test_results.xml --cov-report xml --cov=corbo/ --cov-config .coveragerc |
11 | 11 |
deps = |
12 | 12 |
django18: django>=1.8,<1.9 |
13 |
django111: django>=1.11,<1.12 |
|
13 | 14 |
http://git.entrouvert.org/hobo.git/snapshot/hobo-master.tar.gz |
14 | 15 |
pytest-cov |
15 | 16 |
pytest-django>=3.1.1 |
16 |
- |