summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Cramer <dcramer@gmail.com>2016-08-02 15:21:45 -0700
committerDavid Cramer <dcramer@gmail.com>2016-08-04 11:10:59 -0700
commit5d7cc8cdaf1ba14e671282e725814ad24ba2792f (patch)
tree48dd7d033eec5da403736b290ed79184a582d03a
parentf6e9219936dfa8e76668eda834c53878a9f78428 (diff)
downloadraven-5d7cc8cdaf1ba14e671282e725814ad24ba2792f.tar.gz
Support for Django 1.10
Refs GH-818
-rw-r--r--.travis.yml5
-rw-r--r--conftest.py26
-rw-r--r--raven/contrib/django/management/__init__.py58
-rw-r--r--raven/contrib/django/models.py3
-rw-r--r--raven/contrib/django/urls.py12
-rw-r--r--tests/contrib/django/tests.py57
-rw-r--r--tests/contrib/django/urls.py23
7 files changed, 75 insertions, 109 deletions
diff --git a/.travis.yml b/.travis.yml
index 18de603..1f1e630 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -31,6 +31,7 @@ env:
# - DJANGO=Django==1.7.11
- DJANGO=Django==1.8.7
- DJANGO=Django==1.9
+ - DJANGO=Django==1.10
# - DJANGO="-e git+git://github.com/django/django.git#egg=Django"
install:
- time ci/setup
@@ -52,6 +53,8 @@ matrix:
# env: DJANGO=Django==1.4.20
- python: '3.3'
env: DJANGO=Django==1.9
+ - python: '3.3'
+ env: DJANGO=Django==1.10
# - python: '3.4'
# env: DJANGO=Django==1.4.20
# - python: '3.5'
@@ -69,6 +72,8 @@ matrix:
- python: '3.2'
env: DJANGO="-e git+git://github.com/django/django.git#egg=Django"
- python: '2.6'
+ env: DJANGO=Django==1.10
+ - python: '2.6'
env: DJANGO=Django==1.9
- python: '2.6'
env: DJANGO=Django==1.8.7
diff --git a/conftest.py b/conftest.py
index e353523..55c641c 100644
--- a/conftest.py
+++ b/conftest.py
@@ -11,25 +11,22 @@ if sys.version_info[0] > 2:
collect_ignore.append("tests/handlers/logbook")
try:
- import gevent
+ import gevent # NOQA
except ImportError:
collect_ignore.append("tests/transport/gevent")
try:
- import web
+ import web # NOQA
except ImportError:
collect_ignore.append("tests/contrib/webpy")
INSTALLED_APPS = [
'django.contrib.auth',
- 'django.contrib.admin',
+ 'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
- # Included to fix Disqus' test Django which solves IntegrityMessage case
- 'django.contrib.contenttypes',
-
'raven.contrib.django',
'tests.contrib.django',
]
@@ -37,7 +34,7 @@ INSTALLED_APPS = [
use_djcelery = True
try:
- import djcelery
+ import djcelery # NOQA
INSTALLED_APPS.append('djcelery')
except ImportError:
use_djcelery = False
@@ -59,7 +56,7 @@ def pytest_configure(config):
DATABASE_NAME=':memory:',
TEST_DATABASE_NAME=':memory:',
INSTALLED_APPS=INSTALLED_APPS,
- ROOT_URLCONF='',
+ ROOT_URLCONF='tests.contrib.django.urls',
DEBUG=False,
SITE_ID=1,
BROKER_HOST="localhost",
@@ -70,7 +67,18 @@ def pytest_configure(config):
SENTRY_ALLOW_ORIGIN='*',
CELERY_ALWAYS_EAGER=True,
TEMPLATE_DEBUG=True,
+ LANGUAGE_CODE='en',
+ LANGUAGES=(('en', 'English'),),
PROJECT_ROOT=where_am_i,
- TEMPLATE_DIRS=[os.path.join(where_am_i, 'tests', 'contrib', 'django', 'templates')],
+ TEMPLATE_DIRS=[
+ os.path.join(where_am_i, 'tests', 'contrib', 'django', 'templates'),
+ ],
+ TEMPLATES=[{
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'APP_DIRS': True,
+ 'DIRS': [
+ os.path.join(where_am_i, 'tests', 'contrib', 'django', 'templates'),
+ ],
+ }],
ALLOWED_HOSTS=['*'],
)
diff --git a/raven/contrib/django/management/__init__.py b/raven/contrib/django/management/__init__.py
index 722f6db..b0860a4 100644
--- a/raven/contrib/django/management/__init__.py
+++ b/raven/contrib/django/management/__init__.py
@@ -1,59 +1 @@
-"""
-raven.contrib.django.raven.management
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-:copyright: (c) 2010-2013 by the Sentry Team, see AUTHORS for more details
-:license: BSD, see LICENSE for more details.
-"""
from __future__ import absolute_import, print_function
-
-import sys
-import warnings
-
-from functools import wraps
-
-
-def patch_cli_runner():
- """
- Patches ``cls.execute``, returning a boolean describing if the
- attempt was successful.
- """
- from raven.base import get_excepthook_client
-
- try:
- from django.core.management.base import BaseCommand
- except ImportError:
- warnings.warn('Unable to patch Django management commands')
- return
- else:
- cls = BaseCommand
-
- try:
- original_func = cls.execute
- except AttributeError:
- # must not be a capable version of Django
- return False
-
- if hasattr(original_func, '__raven_patched'):
- return False
-
- @wraps(original_func)
- def new_execute(self, *args, **kwargs):
- try:
- return original_func(self, *args, **kwargs)
- except Exception:
- from raven.contrib.django.models import client
-
- # Since this is an unhandled exception that falls through
- # we only want to log it if the given client is not the
- # one that handles the global exceptions.
- if get_excepthook_client() is not client:
- client.captureException(extra={
- 'argv': sys.argv
- })
- raise
-
- new_execute.__raven_patched = True
- cls.execute = new_execute
-
- return True
diff --git a/raven/contrib/django/models.py b/raven/contrib/django/models.py
index 2e48d5f..8411ddd 100644
--- a/raven/contrib/django/models.py
+++ b/raven/contrib/django/models.py
@@ -18,7 +18,6 @@ import warnings
from django.conf import settings
from raven._compat import PY2, binary_type, text_type, string_types
-from raven.contrib.django.management import patch_cli_runner
from raven.utils.conf import convert_options
from raven.utils.imports import import_string
@@ -215,5 +214,3 @@ if ('raven.contrib.django' in settings.INSTALLED_APPS
or 'raven.contrib.django.raven_compat' in settings.INSTALLED_APPS):
register_handlers()
register_serializers()
-
- patch_cli_runner()
diff --git a/raven/contrib/django/urls.py b/raven/contrib/django/urls.py
index c513e44..de3acec 100644
--- a/raven/contrib/django/urls.py
+++ b/raven/contrib/django/urls.py
@@ -8,12 +8,14 @@ raven.contrib.django.urls
from __future__ import absolute_import
try:
- from django.conf.urls import patterns, url
+ from django.conf.urls import url
except ImportError:
# for Django version less than 1.4
- from django.conf.urls.defaults import patterns, url # NOQA
+ from django.conf.urls.defaults import url # NOQA
-urlpatterns = patterns('',
- url(r'^api/(?:(?P<project_id>[\w_-]+)/)?store/$', 'raven.contrib.django.views.report', name='raven-report'),
- url(r'^report/', 'raven.contrib.django.views.report'),
+import raven.contrib.django.views
+
+urlpatterns = (
+ url(r'^api/(?:(?P<project_id>[\w_-]+)/)?store/$', raven.contrib.django.views.report, name='raven-report'),
+ url(r'^report/', raven.contrib.django.views.report),
)
diff --git a/tests/contrib/django/tests.py b/tests/contrib/django/tests.py
index 21a4a78..3aa6b74 100644
--- a/tests/contrib/django/tests.py
+++ b/tests/contrib/django/tests.py
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-from __future__ import with_statement
+from __future__ import absolute_import, print_function, with_statement
import datetime
import django
@@ -10,9 +9,7 @@ import mock
import pytest
import re
import six
-import sys # NOQA
-from exam import fixture
-from six import StringIO
+import sys
from django.conf import settings
from django.contrib.auth.models import User
@@ -24,6 +21,8 @@ from django.http import QueryDict
from django.template import TemplateSyntaxError
from django.test import TestCase
from django.utils.translation import gettext_lazy
+from exam import fixture
+from six import StringIO
from raven.base import Client
from raven.contrib.django.client import DjangoClient
@@ -42,6 +41,7 @@ from .models import TestModel
settings.SENTRY_CLIENT = 'tests.contrib.django.tests.TempStoreClient'
DJANGO_15 = django.VERSION >= (1, 5, 0)
+DJANGO_18 = django.VERSION >= (1, 8, 0)
def make_request():
@@ -157,7 +157,7 @@ class DjangoClientTest(TestCase):
assert event['message'], "TypeError: int() argument must be a string or a number == not 'NoneType'"
assert event['culprit'] == 'tests.contrib.django.tests in test_signal_integration'
- @pytest.mark.skipif('sys.version_info[:2] == (2, 6)')
+ @pytest.mark.skipif(sys.version_info[:2] == (2, 6), reason='Python 2.6')
def test_view_exception(self):
self.assertRaises(Exception, self.client.get, reverse('sentry-raise-exc'))
@@ -199,7 +199,7 @@ class DjangoClientTest(TestCase):
'email': user.email,
}
- @pytest.mark.skipif(str('not DJANGO_15'))
+ @pytest.mark.skipif(not DJANGO_15, reason='< Django 1.5')
def test_get_user_info_abstract_user(self):
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
@@ -320,6 +320,7 @@ class DjangoClientTest(TestCase):
assert event['culprit'].startswith('django.shortcuts in ')
self.raven.include_paths = include_paths
+ @pytest.mark.skipif(DJANGO_18, reason='Django 1.8+ not supported')
def test_template_name_as_view(self):
self.assertRaises(TemplateSyntaxError, self.client.get, reverse('sentry-template-exc'))
@@ -339,7 +340,7 @@ class DjangoClientTest(TestCase):
# assert event['data']['META']['REMOTE_ADDR'] == '127.0.0.1'
# TODO: Python bug #10805
- @pytest.mark.skipif(str('six.PY3'))
+ @pytest.mark.skipif(six.PY3, reason='Python 2')
def test_record_none_exc_info(self):
# sys.exc_info can return (None, None, None) if no exception is being
# handled anywhere on the stack. See:
@@ -630,62 +631,72 @@ class ReportViewTest(TestCase):
urls = 'raven.contrib.django.urls'
def setUp(self):
- self.path = reverse('raven-report')
+ super(ReportViewTest, self).setUp()
+ self.path = reverse('raven-report', urlconf=self.urls)
@mock.patch('raven.contrib.django.views.is_valid_origin')
def test_calls_is_valid_origin_with_header(self, is_valid_origin):
- self.client.post(self.path, HTTP_ORIGIN='http://example.com')
+ with self.settings(ROOT_URLCONF=self.urls):
+ self.client.post(self.path, HTTP_ORIGIN='http://example.com')
is_valid_origin.assert_called_once_with('http://example.com')
@mock.patch('raven.contrib.django.views.is_valid_origin')
def test_calls_is_valid_origin_with_header_as_get(self, is_valid_origin):
- self.client.get(self.path, HTTP_ORIGIN='http://example.com')
+ with self.settings(ROOT_URLCONF=self.urls):
+ self.client.get(self.path, HTTP_ORIGIN='http://example.com')
is_valid_origin.assert_called_once_with('http://example.com')
@mock.patch('raven.contrib.django.views.is_valid_origin', mock.Mock(return_value=False))
def test_fails_on_invalid_origin(self):
- resp = self.client.post(self.path, HTTP_ORIGIN='http://example.com')
+ with self.settings(ROOT_URLCONF=self.urls):
+ resp = self.client.post(self.path, HTTP_ORIGIN='http://example.com')
assert resp.status_code == 403
@mock.patch('raven.contrib.django.views.is_valid_origin', mock.Mock(return_value=True))
def test_options_call_sends_headers(self):
- resp = self.client.options(self.path, HTTP_ORIGIN='http://example.com')
+ with self.settings(ROOT_URLCONF=self.urls):
+ resp = self.client.options(self.path, HTTP_ORIGIN='http://example.com')
assert resp.status_code == 200
assert resp['Access-Control-Allow-Origin'] == 'http://example.com'
assert resp['Access-Control-Allow-Methods'], 'GET, POST == OPTIONS'
@mock.patch('raven.contrib.django.views.is_valid_origin', mock.Mock(return_value=True))
def test_missing_data(self):
- resp = self.client.post(self.path, HTTP_ORIGIN='http://example.com')
+ with self.settings(ROOT_URLCONF=self.urls):
+ resp = self.client.post(self.path, HTTP_ORIGIN='http://example.com')
assert resp.status_code == 400
@mock.patch('raven.contrib.django.views.is_valid_origin', mock.Mock(return_value=True))
def test_invalid_data(self):
- resp = self.client.post(self.path, HTTP_ORIGIN='http://example.com',
- data='[1', content_type='application/octet-stream')
+ with self.settings(ROOT_URLCONF=self.urls):
+ resp = self.client.post(self.path, HTTP_ORIGIN='http://example.com',
+ data='[1', content_type='application/octet-stream')
assert resp.status_code == 400
@mock.patch('raven.contrib.django.views.is_valid_origin', mock.Mock(return_value=True))
def test_sends_data(self):
- resp = self.client.post(self.path, HTTP_ORIGIN='http://example.com',
- data='{}', content_type='application/octet-stream')
+ with self.settings(ROOT_URLCONF=self.urls):
+ resp = self.client.post(self.path, HTTP_ORIGIN='http://example.com',
+ data='{}', content_type='application/octet-stream')
assert resp.status_code == 200
event = client.events.pop(0)
assert event == {'auth_header': None}
@mock.patch('raven.contrib.django.views.is_valid_origin', mock.Mock(return_value=True))
def test_sends_authorization_header(self):
- resp = self.client.post(self.path, HTTP_ORIGIN='http://example.com',
- HTTP_AUTHORIZATION='Sentry foo/bar', data='{}', content_type='application/octet-stream')
+ with self.settings(ROOT_URLCONF=self.urls):
+ resp = self.client.post(self.path, HTTP_ORIGIN='http://example.com',
+ HTTP_AUTHORIZATION='Sentry foo/bar', data='{}', content_type='application/octet-stream')
assert resp.status_code == 200
event = client.events.pop(0)
assert event == {'auth_header': 'Sentry foo/bar'}
@mock.patch('raven.contrib.django.views.is_valid_origin', mock.Mock(return_value=True))
def test_sends_x_sentry_auth_header(self):
- resp = self.client.post(self.path, HTTP_ORIGIN='http://example.com',
- HTTP_X_SENTRY_AUTH='Sentry foo/bar', data='{}',
- content_type='application/octet-stream')
+ with self.settings(ROOT_URLCONF=self.urls):
+ resp = self.client.post(self.path, HTTP_ORIGIN='http://example.com',
+ HTTP_X_SENTRY_AUTH='Sentry foo/bar', data='{}',
+ content_type='application/octet-stream')
assert resp.status_code == 200
event = client.events.pop(0)
assert event == {'auth_header': 'Sentry foo/bar'}
diff --git a/tests/contrib/django/urls.py b/tests/contrib/django/urls.py
index a1d2929..c4b3abf 100644
--- a/tests/contrib/django/urls.py
+++ b/tests/contrib/django/urls.py
@@ -19,14 +19,15 @@ def handler500(request):
raise ValueError('handler500')
return HttpResponse('', status=500)
-
-urlpatterns = [
- url(r'^no-error$', 'tests.contrib.django.views.no_error', name='sentry-no-error'),
- url(r'^fake-login$', 'tests.contrib.django.views.fake_login', name='sentry-fake-login'),
- url(r'^trigger-500$', 'tests.contrib.django.views.raise_exc', name='sentry-raise-exc'),
- url(r'^trigger-500-ioerror$', 'tests.contrib.django.views.raise_ioerror', name='sentry-raise-ioerror'),
- url(r'^trigger-500-decorated$', 'tests.contrib.django.views.decorated_raise_exc', name='sentry-raise-exc-decor'),
- url(r'^trigger-500-django$', 'tests.contrib.django.views.django_exc', name='sentry-django-exc'),
- url(r'^trigger-500-template$', 'tests.contrib.django.views.template_exc', name='sentry-template-exc'),
- url(r'^trigger-500-log-request$', 'tests.contrib.django.views.logging_request_exc', name='sentry-log-request-exc'),
-]
+import tests.contrib.django.views
+
+urlpatterns = (
+ url(r'^no-error$', tests.contrib.django.views.no_error, name='sentry-no-error'),
+ url(r'^fake-login$', tests.contrib.django.views.fake_login, name='sentry-fake-login'),
+ url(r'^trigger-500$', tests.contrib.django.views.raise_exc, name='sentry-raise-exc'),
+ url(r'^trigger-500-ioerror$', tests.contrib.django.views.raise_ioerror, name='sentry-raise-ioerror'),
+ url(r'^trigger-500-decorated$', tests.contrib.django.views.decorated_raise_exc, name='sentry-raise-exc-decor'),
+ url(r'^trigger-500-django$', tests.contrib.django.views.django_exc, name='sentry-django-exc'),
+ url(r'^trigger-500-template$', tests.contrib.django.views.template_exc, name='sentry-template-exc'),
+ url(r'^trigger-500-log-request$', tests.contrib.django.views.logging_request_exc, name='sentry-log-request-exc'),
+)