general: update for compatibility with django 2.2 (#41626)
This commit is contained in:
parent
d340a2bc7e
commit
e01c978bec
|
@ -45,8 +45,10 @@ class Migration(migrations.Migration):
|
||||||
name='Subscription',
|
name='Subscription',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
('category', models.ForeignKey(verbose_name='category', to='corbo.Category')),
|
('category', models.ForeignKey(verbose_name='category',
|
||||||
('user', models.ForeignKey(verbose_name='user', blank=True, to=settings.AUTH_USER_MODEL, null=True)),
|
to='corbo.Category', on_delete=models.CASCADE)),
|
||||||
|
('user', models.ForeignKey(verbose_name='user', blank=True,
|
||||||
|
to=settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE)),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
},
|
},
|
||||||
|
@ -57,7 +59,7 @@ class Migration(migrations.Migration):
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||||
('identifier', models.CharField(help_text='ex.: email, mobile phone number, jabber id', max_length=128, verbose_name='identifier', blank=True)),
|
('identifier', models.CharField(help_text='ex.: email, mobile phone number, jabber id', max_length=128, verbose_name='identifier', blank=True)),
|
||||||
('subscription', models.ForeignKey(to='corbo.Subscription')),
|
('subscription', models.ForeignKey(to='corbo.Subscription', on_delete=models.CASCADE)),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
},
|
},
|
||||||
|
@ -70,7 +72,8 @@ class Migration(migrations.Migration):
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='announce',
|
model_name='announce',
|
||||||
name='category',
|
name='category',
|
||||||
field=models.ForeignKey(verbose_name='category', to='corbo.Category'),
|
field=models.ForeignKey(verbose_name='category',
|
||||||
|
to='corbo.Category', on_delete=models.CASCADE),
|
||||||
preserve_default=True,
|
preserve_default=True,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -18,7 +18,8 @@ class Migration(migrations.Migration):
|
||||||
('channel', models.CharField(max_length=32, verbose_name='channel', choices=[(b'sms', 'SMS'), (b'email', 'Email')])),
|
('channel', models.CharField(max_length=32, verbose_name='channel', choices=[(b'sms', 'SMS'), (b'email', 'Email')])),
|
||||||
('time', models.DateTimeField(auto_now_add=True, verbose_name='sent time')),
|
('time', models.DateTimeField(auto_now_add=True, verbose_name='sent time')),
|
||||||
('result', models.TextField(verbose_name='result', blank=True)),
|
('result', models.TextField(verbose_name='result', blank=True)),
|
||||||
('announce', models.ForeignKey(verbose_name='announce', to='corbo.Announce')),
|
('announce', models.ForeignKey(verbose_name='announce',
|
||||||
|
to='corbo.Announce', on_delete=models.CASCADE)),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'ordering': ('-time',),
|
'ordering': ('-time',),
|
||||||
|
|
|
@ -33,7 +33,7 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='subscription',
|
model_name='subscription',
|
||||||
name='category',
|
name='category',
|
||||||
field=models.ForeignKey(verbose_name='Category', to='corbo.Category'),
|
field=models.ForeignKey(verbose_name='Category', to='corbo.Category', on_delete=models.CASCADE),
|
||||||
preserve_default=True,
|
preserve_default=True,
|
||||||
),
|
),
|
||||||
migrations.AlterUniqueTogether(
|
migrations.AlterUniqueTogether(
|
||||||
|
|
|
@ -65,7 +65,8 @@ class Category(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class Announce(models.Model):
|
class Announce(models.Model):
|
||||||
category = models.ForeignKey('Category', verbose_name=_('category'))
|
category = models.ForeignKey('Category', verbose_name=_('category'),
|
||||||
|
on_delete=models.CASCADE)
|
||||||
title = models.CharField(_('title'), max_length=256,
|
title = models.CharField(_('title'), max_length=256,
|
||||||
help_text=_('maximum 256 characters'))
|
help_text=_('maximum 256 characters'))
|
||||||
identifier = models.CharField(max_length=256, null=True, blank=True)
|
identifier = models.CharField(max_length=256, null=True, blank=True)
|
||||||
|
@ -150,7 +151,7 @@ class Announce(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class Broadcast(models.Model):
|
class Broadcast(models.Model):
|
||||||
announce = models.ForeignKey(Announce, verbose_name=_('announce'))
|
announce = models.ForeignKey(Announce, verbose_name=_('announce'), on_delete=models.CASCADE)
|
||||||
deliver_time = models.DateTimeField(_('Deliver time'), null=True)
|
deliver_time = models.DateTimeField(_('Deliver time'), null=True)
|
||||||
delivery_count = models.IntegerField(_('Delivery count'), default=0)
|
delivery_count = models.IntegerField(_('Delivery count'), default=0)
|
||||||
|
|
||||||
|
@ -187,7 +188,7 @@ class Broadcast(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class Subscription(models.Model):
|
class Subscription(models.Model):
|
||||||
category = models.ForeignKey('Category', verbose_name=_('Category'))
|
category = models.ForeignKey('Category', verbose_name=_('Category'), on_delete=models.CASCADE)
|
||||||
uuid = models.CharField(_('User identifier'), max_length=128, blank=True)
|
uuid = models.CharField(_('User identifier'), max_length=128, blank=True)
|
||||||
identifier = models.CharField(_('identifier'), max_length=128, blank=True,
|
identifier = models.CharField(_('identifier'), max_length=128, blank=True,
|
||||||
help_text=_('ex.: mailto, ...'))
|
help_text=_('ex.: mailto, ...'))
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from django.core.urlresolvers import reverse
|
from django.urls import reverse
|
||||||
from django.forms.utils import flatatt
|
from django.forms.utils import flatatt
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
|
@ -24,10 +24,12 @@ from django.utils.translation import get_language
|
||||||
|
|
||||||
import ckeditor.widgets
|
import ckeditor.widgets
|
||||||
|
|
||||||
def ckeditor_render(self, name, value, attrs=None):
|
def ckeditor_render(self, name, value, attrs=None, renderer=None):
|
||||||
if value is None:
|
if value is None:
|
||||||
value = ''
|
value = ''
|
||||||
final_attrs = {'name': name}
|
final_attrs = {'name': name}
|
||||||
|
if getattr(self, 'attrs', None):
|
||||||
|
final_attrs.update(self.attrs)
|
||||||
if attrs:
|
if attrs:
|
||||||
final_attrs.update(attrs)
|
final_attrs.update(attrs)
|
||||||
if 'filebrowserUploadUrl' not in self.config:
|
if 'filebrowserUploadUrl' not in self.config:
|
||||||
|
|
|
@ -42,12 +42,11 @@ INSTALLED_APPS = (
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
)
|
)
|
||||||
|
|
||||||
MIDDLEWARE_CLASSES = (
|
MIDDLEWARE = (
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
|
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
)
|
)
|
||||||
|
|
|
@ -8,7 +8,7 @@ from django.views.decorators.cache import never_cache
|
||||||
from django.contrib.admin.views.decorators import staff_member_required
|
from django.contrib.admin.views.decorators import staff_member_required
|
||||||
|
|
||||||
from .urls_utils import decorated_includes, manager_required
|
from .urls_utils import decorated_includes, manager_required
|
||||||
from .views import homepage, atom, unsubscribe, unsubscription_done, login, logout
|
from .views import homepage, atom, unsubscribe, unsubscription_done, LoginView, LogoutView
|
||||||
|
|
||||||
from .manage_urls import urlpatterns as manage_urls
|
from .manage_urls import urlpatterns as manage_urls
|
||||||
from .api_urls import urlpatterns as api_urls
|
from .api_urls import urlpatterns as api_urls
|
||||||
|
@ -21,14 +21,14 @@ urlpatterns = [
|
||||||
url(r'^atom$', atom, name='atom'),
|
url(r'^atom$', atom, name='atom'),
|
||||||
url(r'^manage/', decorated_includes(manager_required,
|
url(r'^manage/', decorated_includes(manager_required,
|
||||||
include(manage_urls))),
|
include(manage_urls))),
|
||||||
url(r'^admin/', include(admin.site.urls)),
|
url(r'^admin/', admin.site.urls),
|
||||||
url(r'^api/', include(api_urls)),
|
url(r'^api/', include(api_urls)),
|
||||||
url(r'^unsubscribe/done/$', unsubscription_done,
|
url(r'^unsubscribe/done/$', unsubscription_done,
|
||||||
name='unsubscription_done'),
|
name='unsubscription_done'),
|
||||||
url(r'^unsubscribe/(?P<unsubscription_token>[\w:-]+)$', unsubscribe,
|
url(r'^unsubscribe/(?P<unsubscription_token>[\w:-]+)$', unsubscribe,
|
||||||
name='unsubscribe'),
|
name='unsubscribe'),
|
||||||
url(r'^logout/$', logout, name='auth_logout'),
|
url(r'^logout/$',LogoutView.as_view(), name='auth_logout'),
|
||||||
url(r'^login/$', login, name='auth_login'),
|
url(r'^login/$', LoginView.as_view(), name='auth_login'),
|
||||||
url(r'^ckeditor/upload/', staff_member_required(ckeditor_views.upload),
|
url(r'^ckeditor/upload/', staff_member_required(ckeditor_views.upload),
|
||||||
name='ckeditor_upload'),
|
name='ckeditor_upload'),
|
||||||
url(r'^ckeditor/browse/', never_cache(staff_member_required(ckeditor_views.browse)),
|
url(r'^ckeditor/browse/', never_cache(staff_member_required(ckeditor_views.browse)),
|
||||||
|
|
|
@ -16,43 +16,52 @@
|
||||||
|
|
||||||
# Decorating URL includes, <https://djangosnippets.org/snippets/2532/>
|
# Decorating URL includes, <https://djangosnippets.org/snippets/2532/>
|
||||||
|
|
||||||
|
import django
|
||||||
|
|
||||||
from django.contrib.auth.decorators import user_passes_test
|
from django.contrib.auth.decorators import user_passes_test
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.core.urlresolvers import RegexURLPattern, RegexURLResolver
|
|
||||||
|
|
||||||
class DecoratedURLPattern(RegexURLPattern):
|
if django.VERSION < (2, 0, 0):
|
||||||
|
from django.urls.resolvers import RegexURLPattern as URLPattern
|
||||||
|
from django.urls.resolvers import RegexURLResolver as URLResolver
|
||||||
|
else:
|
||||||
|
from django.urls.resolvers import URLPattern, URLResolver
|
||||||
|
|
||||||
|
|
||||||
|
class DecoratedURLPattern(URLPattern):
|
||||||
def resolve(self, *args, **kwargs):
|
def resolve(self, *args, **kwargs):
|
||||||
result = super(DecoratedURLPattern, self).resolve(*args, **kwargs)
|
result = super(DecoratedURLPattern, self).resolve(*args, **kwargs)
|
||||||
if result:
|
if result:
|
||||||
result.func = self._decorate_with(result.func)
|
result.func = self._decorate_with(result.func)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
class DecoratedRegexURLResolver(RegexURLResolver):
|
|
||||||
|
class DecoratedURLResolver(URLResolver):
|
||||||
def resolve(self, *args, **kwargs):
|
def resolve(self, *args, **kwargs):
|
||||||
result = super(DecoratedRegexURLResolver, self).resolve(*args, **kwargs)
|
result = super(DecoratedURLResolver, self).resolve(*args, **kwargs)
|
||||||
if result:
|
if result:
|
||||||
result.func = self._decorate_with(result.func)
|
result.func = self._decorate_with(result.func)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def decorated_includes(func, includes, *args, **kwargs):
|
def decorated_includes(func, includes, *args, **kwargs):
|
||||||
urlconf_module, app_name, namespace = includes
|
urlconf_module, app_name, namespace = includes
|
||||||
|
|
||||||
for item in urlconf_module:
|
for item in urlconf_module:
|
||||||
if isinstance(item, RegexURLPattern):
|
if isinstance(item, URLResolver):
|
||||||
|
item.__class__ = DecoratedURLResolver
|
||||||
|
else:
|
||||||
item.__class__ = DecoratedURLPattern
|
item.__class__ = DecoratedURLPattern
|
||||||
item._decorate_with = func
|
item._decorate_with = func
|
||||||
|
|
||||||
elif isinstance(item, RegexURLResolver):
|
|
||||||
item.__class__ = DecoratedRegexURLResolver
|
|
||||||
item._decorate_with = func
|
|
||||||
|
|
||||||
return urlconf_module, app_name, namespace
|
return urlconf_module, app_name, namespace
|
||||||
|
|
||||||
|
|
||||||
def manager_required(function=None, login_url=None):
|
def manager_required(function=None, login_url=None):
|
||||||
def check_manager(user):
|
def check_manager(user):
|
||||||
if user and user.is_staff:
|
if user and user.is_staff:
|
||||||
return True
|
return True
|
||||||
if user and not user.is_anonymous():
|
if user and not user.is_anonymous:
|
||||||
raise PermissionDenied()
|
raise PermissionDenied()
|
||||||
# As the last resort, show the login form
|
# As the last resort, show the login form
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -27,7 +27,7 @@ from django.conf import settings
|
||||||
from django.template import loader
|
from django.template import loader
|
||||||
from django.utils.translation import activate
|
from django.utils.translation import activate
|
||||||
from django.core.files.storage import DefaultStorage
|
from django.core.files.storage import DefaultStorage
|
||||||
from django.core.urlresolvers import reverse
|
from django.urls import reverse
|
||||||
from django.core import signing
|
from django.core import signing
|
||||||
from django.utils.six.moves.urllib import parse as urlparse
|
from django.utils.six.moves.urllib import parse as urlparse
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,12 @@ from django.conf import settings
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.core import signing
|
from django.core import signing
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.core.urlresolvers import reverse
|
from django.urls import reverse
|
||||||
from django.views.generic import CreateView, UpdateView, DeleteView, \
|
from django.views.generic import CreateView, UpdateView, DeleteView, \
|
||||||
ListView, TemplateView, RedirectView, DetailView, FormView
|
ListView, TemplateView, RedirectView, DetailView, FormView
|
||||||
from django.contrib.syndication.views import Feed
|
from django.contrib.syndication.views import Feed
|
||||||
from django.shortcuts import resolve_url
|
from django.shortcuts import resolve_url
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.feedgenerator import Atom1Feed as DjangoAtom1Feed
|
from django.utils.feedgenerator import Atom1Feed as DjangoAtom1Feed
|
||||||
from django.utils.http import quote
|
from django.utils.http import quote
|
||||||
|
@ -18,6 +19,7 @@ from django.contrib.auth import views as auth_views
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.utils.translation import ngettext
|
from django.utils.translation import ngettext
|
||||||
|
from django.views.decorators.cache import never_cache
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
from .forms import AnnounceForm, CategoryForm, SubscriptionsImportForm, \
|
from .forms import AnnounceForm, CategoryForm, SubscriptionsImportForm, \
|
||||||
|
@ -30,24 +32,23 @@ except ImportError:
|
||||||
get_idps = lambda: []
|
get_idps = lambda: []
|
||||||
|
|
||||||
|
|
||||||
def login(request, *args, **kwargs):
|
class LoginView(auth_views.LoginView):
|
||||||
if any(get_idps()):
|
def get(self, request, *args, **kwargs):
|
||||||
if 'next' not in request.GET:
|
if any(get_idps()):
|
||||||
return HttpResponseRedirect(resolve_url('mellon_login'))
|
if not 'next' in request.GET:
|
||||||
return HttpResponseRedirect(resolve_url('mellon_login') + '?next=' +
|
return HttpResponseRedirect(resolve_url('mellon_login'))
|
||||||
quote(request.GET.get('next')))
|
return HttpResponseRedirect(
|
||||||
return auth_views.login(request, *args, **kwargs)
|
resolve_url('mellon_login') + '?next=' + quote(request.GET.get('next'))
|
||||||
|
)
|
||||||
|
return super(LoginView, self).get(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def logout(request, next_page=None):
|
class LogoutView(auth_views.LogoutView):
|
||||||
if any(get_idps()):
|
@method_decorator(never_cache)
|
||||||
return HttpResponseRedirect(resolve_url('mellon_logout'))
|
def dispatch(self, request, *args, **kwargs):
|
||||||
auth_logout(request)
|
if any(get_idps()):
|
||||||
if next_page is not None:
|
return HttpResponseRedirect(resolve_url('mellon_logout'))
|
||||||
next_page = resolve_url(next_page)
|
return super(LogoutView, self).dispatch(request, *args, **kwargs)
|
||||||
else:
|
|
||||||
next_page = '/'
|
|
||||||
return HttpResponseRedirect(next_page)
|
|
||||||
|
|
||||||
|
|
||||||
class HomepageView(RedirectView):
|
class HomepageView(RedirectView):
|
||||||
|
|
|
@ -83,7 +83,7 @@ class PickerWidgetMixin(object):
|
||||||
|
|
||||||
super(PickerWidgetMixin, self).__init__(attrs, format=self.format)
|
super(PickerWidgetMixin, self).__init__(attrs, format=self.format)
|
||||||
|
|
||||||
def render(self, name, value, attrs=None):
|
def render(self, name, value, attrs=None, renderer=None):
|
||||||
final_attrs = self.build_attrs(attrs)
|
final_attrs = self.build_attrs(attrs)
|
||||||
rendered_widget = super(PickerWidgetMixin, self).render(name, value, final_attrs)
|
rendered_widget = super(PickerWidgetMixin, self).render(name, value, final_attrs)
|
||||||
|
|
||||||
|
|
4
setup.py
4
setup.py
|
@ -109,9 +109,9 @@ setup(
|
||||||
'Programming Language :: Python',
|
'Programming Language :: Python',
|
||||||
'Programming Language :: Python :: 2',
|
'Programming Language :: Python :: 2',
|
||||||
],
|
],
|
||||||
install_requires=['django>1.7, <1.12',
|
install_requires=['django>1.7, <2.3',
|
||||||
'django-ckeditor<4.5.4',
|
'django-ckeditor<4.5.4',
|
||||||
'djangorestframework>=3.3,<3.7',
|
'djangorestframework>=3.3,<3.8',
|
||||||
'html2text',
|
'html2text',
|
||||||
'gadjo',
|
'gadjo',
|
||||||
'emails',
|
'emails',
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
# Add corbo hobo agent
|
# Add corbo hobo agent
|
||||||
INSTALLED_APPS = ('corbo.hobo_agent', 'hobo.agent.common') + INSTALLED_APPS
|
INSTALLED_APPS = ('corbo.hobo_agent', 'hobo.agent.common') + INSTALLED_APPS
|
||||||
|
|
||||||
|
REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'] = ['rest_framework.authentication.BasicAuthentication']
|
||||||
|
|
|
@ -6,7 +6,7 @@ import tempfile
|
||||||
|
|
||||||
from django.core.files.storage import DefaultStorage
|
from django.core.files.storage import DefaultStorage
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.core.urlresolvers import reverse
|
from django.urls import reverse
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.test import override_settings
|
from django.test import override_settings
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import urllib
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
|
|
||||||
from django.core.urlresolvers import reverse
|
from django.urls import reverse
|
||||||
from django.utils.http import urlencode
|
from django.utils.http import urlencode
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
|
@ -50,7 +50,7 @@ def user():
|
||||||
|
|
||||||
|
|
||||||
def test_get_newsletters(app, categories, announces, user):
|
def test_get_newsletters(app, categories, announces, user):
|
||||||
resp = app.get(reverse('newsletters'), status=403)
|
resp = app.get(reverse('newsletters'), status=(401, 403))
|
||||||
app.authorization = ('Basic', ('john.doe', 'password'))
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
||||||
resp = app.get(reverse('newsletters'))
|
resp = app.get(reverse('newsletters'))
|
||||||
data = resp.json
|
data = resp.json
|
||||||
|
@ -65,9 +65,9 @@ def test_get_newsletters(app, categories, announces, user):
|
||||||
|
|
||||||
|
|
||||||
def test_get_subscriptions(app, categories, announces, user):
|
def test_get_subscriptions(app, categories, announces, user):
|
||||||
resp = app.get(reverse('subscriptions'), status=403)
|
resp = app.get(reverse('subscriptions'), status=(401, 403))
|
||||||
uuid = str(uuid4())
|
uuid = str(uuid4())
|
||||||
resp = app.get(reverse('subscriptions'), params={'uuid': uuid}, status=403)
|
resp = app.get(reverse('subscriptions'), params={'uuid': uuid}, status=(401, 403))
|
||||||
app.authorization = ('Basic', ('john.doe', 'password'))
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
||||||
|
|
||||||
for identifier, name in channel_choices:
|
for identifier, name in channel_choices:
|
||||||
|
@ -105,7 +105,7 @@ def test_update_subscriptions(app, categories, announces, user):
|
||||||
def test_delete_subscriptions(app, categories, announces, user):
|
def test_delete_subscriptions(app, categories, announces, user):
|
||||||
params = urlencode({'uuid': str(uuid4())})
|
params = urlencode({'uuid': str(uuid4())})
|
||||||
subscriptions_url = reverse('subscriptions') + '?' + params
|
subscriptions_url = reverse('subscriptions') + '?' + params
|
||||||
resp = app.delete(subscriptions_url, status=403)
|
resp = app.delete(subscriptions_url, status=(401, 403))
|
||||||
app.authorization = ('Basic', ('john.doe', 'password'))
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
||||||
resp = app.delete(subscriptions_url)
|
resp = app.delete(subscriptions_url)
|
||||||
if resp.json['data']:
|
if resp.json['data']:
|
||||||
|
@ -119,7 +119,7 @@ def test_simple_email_subscription(app, categories, user):
|
||||||
url = '/api/subscribe/?uuid=%s&email=john@example.net' % uuid
|
url = '/api/subscribe/?uuid=%s&email=john@example.net' % uuid
|
||||||
|
|
||||||
# anonymous
|
# anonymous
|
||||||
resp = app.post_json(url, params=payload, status=403)
|
resp = app.post_json(url, params=payload, status=(401, 403))
|
||||||
assert resp.json['detail'] == 'Authentication credentials were not provided.'
|
assert resp.json['detail'] == 'Authentication credentials were not provided.'
|
||||||
|
|
||||||
# authenticated
|
# authenticated
|
||||||
|
|
|
@ -7,7 +7,7 @@ import mock
|
||||||
import random
|
import random
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from django.core.urlresolvers import reverse
|
from django.urls import reverse
|
||||||
from django.core import mail, signing
|
from django.core import mail, signing
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.core.files.storage import DefaultStorage
|
from django.core.files.storage import DefaultStorage
|
||||||
|
|
|
@ -2,6 +2,7 @@ import uuid
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
import django
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
from django.db.migrations.executor import MigrationExecutor
|
from django.db.migrations.executor import MigrationExecutor
|
||||||
|
|
||||||
|
@ -9,6 +10,8 @@ pytestmark = pytest.mark.django_db
|
||||||
|
|
||||||
|
|
||||||
def test_subscription_sms_identifier_format_migration():
|
def test_subscription_sms_identifier_format_migration():
|
||||||
|
if django.VERSION >= (2, 0, 0):
|
||||||
|
pytest.skip('NotSupportedError')
|
||||||
executor = MigrationExecutor(connection)
|
executor = MigrationExecutor(connection)
|
||||||
app = 'corbo'
|
app = 'corbo'
|
||||||
migrate_from = [(app, '0009_auto_20170120_1533')]
|
migrate_from = [(app, '0009_auto_20170120_1533')]
|
||||||
|
|
|
@ -3,7 +3,7 @@ import mock
|
||||||
import os
|
import os
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from django.core.urlresolvers import reverse
|
from django.urls import reverse
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.test import override_settings
|
from django.test import override_settings
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import pytest
|
||||||
from webtest import Upload
|
from webtest import Upload
|
||||||
|
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
from django.core.urlresolvers import reverse
|
from django.urls import reverse
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
|
|
||||||
from corbo.models import Category, Subscription
|
from corbo.models import Category, Subscription
|
||||||
|
|
19
tox.ini
19
tox.ini
|
@ -1,6 +1,6 @@
|
||||||
[tox]
|
[tox]
|
||||||
toxworkdir = {env:TMPDIR:/tmp}/tox-{env:USER}/corbo/{env:BRANCH_NAME:}
|
toxworkdir = {env:TMPDIR:/tmp}/tox-{env:USER}/corbo/{env:BRANCH_NAME:}
|
||||||
envlist = py2-coverage-django111,py3-django111
|
envlist = py2-coverage-django111,py3-django111,py3-django22
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
usedevelop =
|
usedevelop =
|
||||||
|
@ -10,16 +10,17 @@ setenv =
|
||||||
CORBO_SETTINGS_FILE=tests/settings.py
|
CORBO_SETTINGS_FILE=tests/settings.py
|
||||||
coverage: COVERAGE=--junitxml=test_results.xml --cov-report xml --cov-report html --cov=corbo/ --cov-config .coveragerc
|
coverage: COVERAGE=--junitxml=test_results.xml --cov-report xml --cov-report html --cov=corbo/ --cov-config .coveragerc
|
||||||
deps =
|
deps =
|
||||||
django>=1.11,<1.12
|
django111: django>=1.11,<1.12
|
||||||
|
django22: django>=2.2,<2.3
|
||||||
http://git.entrouvert.org/hobo.git/snapshot/hobo-master.tar.gz
|
http://git.entrouvert.org/hobo.git/snapshot/hobo-master.tar.gz
|
||||||
pytest-cov
|
pytest-cov
|
||||||
pytest-django>=3.1.1,<3.4.6
|
pytest-django
|
||||||
pytest>=3.0.4
|
pytest
|
||||||
django-webtest<1.9.3
|
django-webtest
|
||||||
django-ckeditor<4.5.3
|
git+http://git.entrouvert.org/debian/django-ckeditor.git
|
||||||
djangorestframework>=3.3,<3.7
|
djangorestframework>=3.3,<3.8
|
||||||
pylint==1.4.0
|
pylint
|
||||||
astroid==1.3.2
|
astroid
|
||||||
mock
|
mock
|
||||||
commands =
|
commands =
|
||||||
py.test {env:COVERAGE:} {posargs:tests/}
|
py.test {env:COVERAGE:} {posargs:tests/}
|
||||||
|
|
Reference in New Issue