Skip to content

Commit 318dde3

Browse files
authored
Merge pull request #297 from goranpavlovic/master
Python > 3.5 (3.5 - 3.9) and django > 2.x and 3.x (latest tested is 3.2.2)
2 parents 4723874 + 772d9eb commit 318dde3

File tree

7 files changed

+144
-51
lines changed

7 files changed

+144
-51
lines changed

.travis.yml

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,49 +2,95 @@ language: python
22

33
python:
44
- 2.7
5-
- 3.4
65
- 3.5
76
- 3.6
7+
- 3.7
8+
- 3.8
9+
- 3.9
810

911
env:
1012
- DJANGO=1.7.11
1113
- DJANGO=1.8.19
1214
- DJANGO=1.9.13
1315
- DJANGO=1.10.8
14-
- DJANGO=1.11.13
15-
- DJANGO=2.0.5
16-
- DJANGO=2.1.5
16+
- DJANGO=1.11.29
17+
- DJANGO=2.0.13
18+
- DJANGO=2.1.15
19+
- DJANGO=2.2.22
20+
- DJANGO=3.0.14
21+
- DJANGO=3.1.10
22+
- DJANGO=3.2.2
1723

1824
branches:
1925
only:
2026
- master
2127

2228
matrix:
2329
exclude:
24-
- env: DJANGO=1.7.11
25-
python: 3.4
2630
- env: DJANGO=1.7.11
2731
python: 3.5
2832
- env: DJANGO=1.7.11
2933
python: 3.6
34+
- env: DJANGO=1.7.11
35+
python: 3.7
36+
- env: DJANGO=1.7.11
37+
python: 3.8
38+
- env: DJANGO=1.7.11
39+
python: 3.9
40+
- env: DJANGO=1.8.19
41+
python: 3.6
3042
- env: DJANGO=1.8.19
31-
python: 3.4
43+
python: 3.7
3244
- env: DJANGO=1.8.19
33-
python: 3.5
45+
python: 3.8
3446
- env: DJANGO=1.8.19
47+
python: 3.9
48+
- env: DJANGO=1.9.13
3549
python: 3.6
3650
- env: DJANGO=1.9.13
37-
python: 3.4
51+
python: 3.7
3852
- env: DJANGO=1.9.13
39-
python: 3.5
53+
python: 3.8
4054
- env: DJANGO=1.9.13
55+
python: 3.9
56+
- env: DJANGO=1.10.8
4157
python: 3.6
42-
- env: DJANGO=2.0.5
58+
- env: DJANGO=1.10.8
59+
python: 3.7
60+
- env: DJANGO=1.10.8
61+
python: 3.8
62+
- env: DJANGO=1.10.8
63+
python: 3.9
64+
- env: DJANGO=1.11.29
65+
python: 3.8
66+
- env: DJANGO=1.11.29
67+
python: 3.9
68+
- env: DJANGO=2.0.13
69+
python: 2.7
70+
- env: DJANGO=2.0.13
71+
python: 3.8
72+
- env: DJANGO=2.0.13
73+
python: 3.9
74+
- env: DJANGO=2.1.15
75+
python: 2.7
76+
- env: DJANGO=2.1.15
77+
python: 3.8
78+
- env: DJANGO=2.1.15
79+
python: 3.9
80+
- env: DJANGO=2.2.22
81+
python: 2.7
82+
- env: DJANGO=3.0.14
4383
python: 2.7
44-
- env: DJANGO=2.1.5
84+
- env: DJANGO=3.0.14
85+
python: 3.5
86+
- env: DJANGO=3.1.10
87+
python: 2.7
88+
- env: DJANGO=3.1.10
89+
python: 3.5
90+
- env: DJANGO=3.2.2
4591
python: 2.7
46-
- env: DJANGO=2.1.5
47-
python: 3.4
92+
- env: DJANGO=3.2.2
93+
python: 3.5
4894

4995
install:
5096
- pip install -r examples/requirements.txt
@@ -58,4 +104,4 @@ before_script:
58104
- pip freeze
59105

60106
script:
61-
- cd examples && ./manage.py migrate && ./manage.py test chatserver --settings=chatserver.tests.settings
107+
- cd examples && ./manage.py migrate --settings=chatserver.tests.settings && ./manage.py test chatserver --settings=chatserver.tests.settings

examples/chatserver/templatetags/tutorial_tags.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# -*- coding: utf-8 -*-
22
from django import template
3-
from django.core.urlresolvers import reverse
3+
4+
try:
5+
from django.core.urlresolvers import reverse
6+
except ImportError as e:
7+
from django.urls import reverse
48

59
register = template.Library()
610

examples/chatserver/tests/settings.py

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import django
2+
from distutils.version import StrictVersion
13
# Django settings for unit test project.
24

35
DEBUG = True
@@ -37,20 +39,38 @@
3739
SESSION_REDIS_PREFIX = 'session'
3840

3941
# List of callables that know how to import templates from various sources.
40-
TEMPLATE_LOADERS = (
41-
'django.template.loaders.app_directories.Loader',
42-
)
42+
if StrictVersion(django.get_version()) < StrictVersion('2.0'):
43+
TEMPLATE_LOADERS = (
44+
'django.template.loaders.app_directories.Loader',
45+
)
46+
47+
TEMPLATE_CONTEXT_PROCESSORS = (
48+
'django.contrib.auth.context_processors.auth',
49+
'django.core.context_processors.static',
50+
'django.core.context_processors.request',
51+
'ws4redis.context_processors.default',
52+
)
53+
else:
54+
TEMPLATES = [
55+
{
56+
'BACKEND': 'django.template.backends.django.DjangoTemplates',
57+
'OPTIONS': {
58+
'loaders': (
59+
'django.template.loaders.app_directories.Loader',
60+
),
61+
'context_processors': {
62+
'django.contrib.auth.context_processors.auth',
63+
'django.core.context_processors.static',
64+
'django.core.context_processors.request',
65+
'ws4redis.context_processors.default',
66+
'django.contrib.messages.context_processors.messages'
67+
}
68+
}
69+
},
70+
]
4371

4472
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
4573

46-
47-
TEMPLATE_CONTEXT_PROCESSORS = (
48-
'django.contrib.auth.context_processors.auth',
49-
'django.core.context_processors.static',
50-
'django.core.context_processors.request',
51-
'ws4redis.context_processors.default',
52-
)
53-
5474
INSTALLED_APPS = (
5575
'django.contrib.admin',
5676
'django.contrib.auth',
@@ -65,15 +85,27 @@
6585

6686
# These two middleware classes must be present, if messages sent or received through a websocket
6787
# connection shall be delivered to an authenticated Django user.
68-
MIDDLEWARE_CLASSES = (
69-
'django.contrib.sessions.middleware.SessionMiddleware',
70-
'django.middleware.common.CommonMiddleware',
71-
'django.middleware.csrf.CsrfViewMiddleware',
72-
'django.contrib.auth.middleware.AuthenticationMiddleware',
73-
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
74-
'django.contrib.messages.middleware.MessageMiddleware',
75-
'django.middleware.clickjacking.XFrameOptionsMiddleware',
76-
)
88+
if StrictVersion(django.get_version()) < StrictVersion('2.0'):
89+
print("DEBUG " + django.get_version())
90+
MIDDLEWARE_CLASSES = (
91+
'django.contrib.sessions.middleware.SessionMiddleware',
92+
'django.middleware.common.CommonMiddleware',
93+
'django.middleware.csrf.CsrfViewMiddleware',
94+
'django.contrib.auth.middleware.AuthenticationMiddleware',
95+
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
96+
'django.contrib.messages.middleware.MessageMiddleware',
97+
'django.middleware.clickjacking.XFrameOptionsMiddleware',
98+
)
99+
else:
100+
print("DEBUG " + django.get_version())
101+
MIDDLEWARE = (
102+
'django.contrib.sessions.middleware.SessionMiddleware',
103+
'django.middleware.common.CommonMiddleware',
104+
'django.middleware.csrf.CsrfViewMiddleware',
105+
'django.contrib.auth.middleware.AuthenticationMiddleware',
106+
'django.contrib.messages.middleware.MessageMiddleware',
107+
'django.middleware.clickjacking.XFrameOptionsMiddleware',
108+
)
77109

78110
# This setting is required to override the Django's main loop, when running in
79111
# development mode, such as ./manage runserver

examples/requirements.txt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
backports.ssl-match-hostname==3.4.0.2
2-
django-nose
3-
django-redis-sessions==0.5.0
1+
backports.ssl-match-hostname==3.7.0.1
2+
django-nose==1.4.7
3+
django-redis-sessions==0.6.2
44
django-websocket-redis==0.4.5
5-
gevent==1.0.2
6-
greenlet==0.4.9
5+
gevent==21.1.2
6+
greenlet==1.1.0
77
nose==1.3.7
8-
redis==2.10.3
9-
requests==2.20.0
10-
six==1.10.0
11-
websocket-client==0.35.0
8+
redis==3.5.3
9+
requests==2.25.1
10+
six==1.16.0
11+
websocket-client==0.59.0

setup.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def convert(filename, fmt):
1313
with io.open(filename, encoding='utf-8') as fd:
1414
return fd.read()
1515

16-
DESCRIPTION = 'Websocket support for Django using Redis as datastore'
16+
DESCRIPTION = 'Websockets support for Django using Redis as datastore'
1717

1818
CLASSIFIERS = [
1919
'Environment :: Web Environment',
@@ -22,17 +22,23 @@ def convert(filename, fmt):
2222
'Framework :: Django :: 1.6',
2323
'Framework :: Django :: 1.7',
2424
'Framework :: Django :: 1.8',
25+
'Framework :: Django :: 1.9',
26+
'Framework :: Django :: 2.0',
27+
'Framework :: Django :: 3.0',
28+
'Framework :: Django :: 3.1',
29+
'Framework :: Django :: 3.2',
2530
'Intended Audience :: Developers',
2631
'License :: OSI Approved :: MIT License',
2732
'Operating System :: OS Independent',
2833
'Programming Language :: Python',
2934
'Topic :: Software Development :: Libraries :: Python Modules',
3035
'Development Status :: 4 - Beta',
3136
'Programming Language :: Python :: 2.7',
32-
'Programming Language :: Python :: 3.3',
33-
'Programming Language :: Python :: 3.4',
3437
'Programming Language :: Python :: 3.5',
3538
'Programming Language :: Python :: 3.6',
39+
'Programming Language :: Python :: 3.7',
40+
'Programming Language :: Python :: 3.8',
41+
'Programming Language :: Python :: 3.9',
3642
]
3743

3844
setup(

ws4redis/django_runserver.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@
1010
from django.core.servers.basehttp import WSGIServer, ServerHandler as _ServerHandler, WSGIRequestHandler as _WSGIRequestHandler
1111
from django.conf import settings
1212
from django.core.management.commands import runserver
13-
from django.utils.six.moves import socketserver
13+
try:
14+
from django.utils.six.moves import socketserver
15+
except ModuleNotFoundError as e:
16+
import socketserver
1417
from django.utils.encoding import force_str
1518
from ws4redis.websocket import WebSocket
1619
from ws4redis.wsgi_server import WebsocketWSGIServer, HandshakeError, UpgradeRequiredError

ws4redis/wsgi_server.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,10 @@ def __call__(self, environ, start_response):
171171
logger.warning('Starting late response on websocket')
172172
status_text = http_client.responses.get(response.status_code, 'UNKNOWN STATUS CODE')
173173
status = '{0} {1}'.format(response.status_code, status_text)
174-
headers = response._headers.values()
175-
if six.PY3:
174+
headers = response._headers.values() if hasattr(response, '_headers') else \
175+
[(item, response.headers[item]) for item in response.headers]
176+
177+
if six.PY3 and not isinstance(headers, list):
176178
headers = list(headers)
177179
start_response(force_str(status), headers)
178180
logger.info('Finish non-websocket response with status code: {}'.format(response.status_code))

0 commit comments

Comments
 (0)