Skip to content

Commit 77e39fd

Browse files
authored
* fix bugs in older django versions, set up CI * remove py26 support * fix pytest-django installation * fix build matrix * django <1.7 is broken in py35+
1 parent 1811a66 commit 77e39fd

7 files changed

Lines changed: 134 additions & 42 deletions

File tree

.travis.yml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
language: python
2+
sudo: false
3+
4+
matrix:
5+
include:
6+
- python: "2.7"
7+
env: DJANGO_VERSION=1.4.*
8+
- python: "2.7"
9+
env: DJANGO_VERSION=1.5.*
10+
- python: "2.7"
11+
env: DJANGO_VERSION=1.6.*
12+
- python: "2.7"
13+
env: DJANGO_VERSION=1.7.*
14+
- python: "2.7"
15+
env: DJANGO_VERSION=1.8.*
16+
- python: "2.7"
17+
env: DJANGO_VERSION=1.9.*
18+
19+
- python: "3.4"
20+
env: DJANGO_VERSION=1.5.*
21+
- python: "3.4"
22+
env: DJANGO_VERSION=1.6.*
23+
- python: "3.4"
24+
env: DJANGO_VERSION=1.7.*
25+
- python: "3.4"
26+
env: DJANGO_VERSION=1.8.*
27+
- python: "3.4"
28+
env: DJANGO_VERSION=1.9.*
29+
- python: "3.4"
30+
env: DJANGO_VERSION=2.0.*
31+
32+
- python: "3.5"
33+
env: DJANGO_VERSION=1.8.*
34+
- python: "3.5"
35+
env: DJANGO_VERSION=1.9.*
36+
- python: "3.5"
37+
env: DJANGO_VERSION=2.0.*
38+
39+
- python: "3.6"
40+
env: DJANGO_VERSION=1.8.*
41+
- python: "3.6"
42+
env: DJANGO_VERSION=1.9.*
43+
- python: "3.6"
44+
env: DJANGO_VERSION=2.0.*
45+
46+
- python: "3.6"
47+
env: DJANGO_VERSION=1.8.*
48+
- python: "3.6"
49+
env: DJANGO_VERSION=1.9.*
50+
- python: "3.6"
51+
env: DJANGO_VERSION=2.0.*
52+
53+
- python: "3.7-dev"
54+
env: DJANGO_VERSION=1.8.*
55+
- python: "3.7-dev"
56+
env: DJANGO_VERSION=1.9.*
57+
- python: "3.7-dev"
58+
env: DJANGO_VERSION=2.0.*
59+
60+
install:
61+
- pip install -e .
62+
- pip install -Ur dev-requirements.txt
63+
- pip install -U "django==$DJANGO_VERSION"
64+
- |
65+
if [ "$DJANGO_VERSION" = 1.4.* ] || [ "$DJANGO_VERSION" = 1.5.* ] || [ "$DJANGO_VERSION" = 1.6.* ] || [ "$DJANGO_VERSION" = 1.7.* ] || [ "$DJANGO_VERSION" = 1.8.* ]; then
66+
pip install 'pytest-django<3.0';
67+
fi
68+
69+
script:
70+
- pytest # or py.test for Python versions 3.5 and below

dev-requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pytest
22
pytest-django
3+
django

sentry_sdk/integrations/django/__init__.py

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
from __future__ import absolute_import
2+
13
from threading import Lock, local
24

3-
from django.apps import AppConfig
45
from django.conf import settings
56
from django.core import signals
6-
from django.urls import resolve
7+
try:
8+
from django.urls import resolve
9+
except ImportError:
10+
from django.core.urlresolvers import resolve
711

812
from sentry_sdk import get_current_hub, configure_scope, capture_exception
913

@@ -25,19 +29,17 @@ def _get_transaction_from_request(request):
2529
# request_started (or any other signal) cannot be used because the request is
2630
# not yet available
2731
class SentryMiddleware(MiddlewareMixin):
28-
def process_view(self, request, func, args, kwargs):
32+
def process_request(self, request):
33+
assert getattr(_request_scope, 'manager', None) is None, 'race condition'
34+
_request_scope.manager = get_current_hub().push_scope().__enter__()
35+
2936
try:
3037
with configure_scope() as scope:
3138
scope.transaction = _get_transaction_from_request(request)
3239
except Exception:
3340
capture_exception()
3441

3542

36-
def _request_started(*args, **kwargs):
37-
assert getattr(_request_scope, 'manager', None) is None, 'race condition'
38-
_request_scope.manager = get_current_hub().push_scope().__enter__()
39-
40-
4143
def _request_finished(*args, **kwargs):
4244
assert getattr(_request_scope, 'manager', None) is not None, 'race condition'
4345
_request_scope.manager.__exit__(None, None, None)
@@ -86,18 +88,24 @@ def _initialize_impl():
8688
middleware_attr,
8789
[MIDDLEWARE_NAME] + list(middleware))
8890

89-
signals.request_started.connect(_request_started)
9091
signals.request_finished.connect(_request_finished)
9192
signals.got_request_exception.connect(_got_request_exception)
9293

9394

94-
default_app_config = 'sentry_sdk.integrations.django.SentryConfig'
9595

9696

97-
class SentryConfig(AppConfig):
98-
name = 'sentry_sdk.integrations.django'
99-
label = 'sentry_sdk_integrations_django'
100-
verbose_name = 'Sentry'
97+
try:
98+
# Django >= 1.7
99+
from django.apps import AppConfig
100+
except ImportError:
101+
initialize()
102+
else:
103+
class SentryConfig(AppConfig):
104+
name = 'sentry_sdk.integrations.django'
105+
label = 'sentry_sdk_integrations_django'
106+
verbose_name = 'Sentry'
107+
108+
def ready(self):
109+
initialize()
101110

102-
def ready(self):
103-
initialize()
111+
default_app_config = 'sentry_sdk.integrations.django.SentryConfig'

tests/django/myapp/settings.py

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@
1111
"""
1212

1313
import os
14+
import sentry_sdk
15+
16+
try:
17+
# Django >= 1.10
18+
from django.utils.deprecation import MiddlewareMixin
19+
except ImportError:
20+
# Not required for Django <= 1.9, see:
21+
# https://docs.djangoproject.com/en/1.10/topics/http/middleware/#upgrading-pre-django-1-10-style-middleware
22+
MiddlewareMixin = object
1423

1524
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
1625
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -39,26 +48,29 @@
3948
'sentry_sdk.integrations.django'
4049
]
4150

42-
class TestMiddleware(object):
43-
def __init__(self, get_response):
44-
self.get_response = get_response
4551

46-
def __call__(self, request):
52+
class TestMiddleware(MiddlewareMixin):
53+
def process_request(self, request):
4754
if 'middleware-exc' in request.path:
4855
1/0
49-
return get_response(request)
5056

57+
with sentry_sdk.configure_scope() as scope:
58+
assert scope._data['transaction'] is not None
59+
60+
def process_response(self, request, response):
61+
with sentry_sdk.configure_scope() as scope:
62+
assert scope._data['transaction'] is not None
63+
64+
return response
5165

52-
MIDDLEWARE = [
53-
'django.middleware.security.SecurityMiddleware',
54-
'django.contrib.sessions.middleware.SessionMiddleware',
55-
'django.middleware.common.CommonMiddleware',
56-
'django.middleware.csrf.CsrfViewMiddleware',
57-
'django.contrib.auth.middleware.AuthenticationMiddleware',
58-
'django.contrib.messages.middleware.MessageMiddleware',
59-
'django.middleware.clickjacking.XFrameOptionsMiddleware'
66+
MIDDLEWARE_CLASSES = [
67+
'tests.django.myapp.settings.TestMiddleware'
6068
]
6169

70+
if MiddlewareMixin is not object:
71+
MIDDLEWARE = MIDDLEWARE_CLASSES
72+
73+
6274
ROOT_URLCONF = 'tests.django.myapp.urls'
6375

6476
TEMPLATES = [

tests/django/myapp/urls.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,18 @@
1313
1. Import the include() function: from django.urls import include, path
1414
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
1515
"""
16-
from django.contrib import admin
17-
from django.urls import path
16+
from __future__ import absolute_import
17+
18+
try:
19+
from django.urls import path
20+
except ImportError:
21+
from django.conf.urls import url as path
1822

1923
from . import views
2024

2125
urlpatterns = [
2226
path('self-check', views.self_check, name='self_check'),
2327
path('view-exc', views.view_exc, name='view_exc'),
24-
path('middleware-exc', views.view_exc, name='middleware_exc'),
28+
path('middleware-exc', views.self_check, name='middleware_exc'),
2529
path('get-dsn', views.get_dsn, name='get_dsn')
2630
]

tests/django/myapp/views.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from django.http import HttpResponse
2-
from django.template import engines
2+
from django.template import Template, Context
33

44
import sentry_sdk
55

@@ -8,11 +8,6 @@
88
def self_check(request):
99
with sentry_sdk.configure_scope() as scope:
1010
assert scope._data['transaction'] == self_check
11-
scope.set_tag('foo', 'bar')
12-
13-
with sentry_sdk.configure_scope() as scope:
14-
# ensure scope did not get popped
15-
assert scope._data['transaction'] == self_check
1611
return HttpResponse("ok")
1712

1813

@@ -21,11 +16,10 @@ def view_exc(request):
2116

2217

2318
def get_dsn(request):
24-
django_engine = engines['django']
25-
template = django_engine.from_string(
19+
template = Template(
2620
"{% load sentry %}{% sentry_dsn %}!"
2721
)
2822
return HttpResponse(
29-
template.render({}, request),
23+
template.render(Context()),
3024
content_type='application/xhtml+xml'
3125
)

tests/django/test_basic.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
from django.test import Client
66
from django.test.utils import setup_test_environment
7-
from django.urls import reverse
7+
try:
8+
from django.urls import reverse
9+
except ImportError:
10+
from django.core.urlresolvers import reverse
811

912
from sentry_sdk import Hub, Client as SentryClient
1013

0 commit comments

Comments
 (0)