Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed import to support Django>=1.9. #236

Merged
merged 7 commits into from
Mar 14, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,5 @@ nohup.out

.project
.pydevproject
.idea/
.idea/
/.cache/
9 changes: 7 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ language: python
python:
- "2.6"
- "2.7"
- "3.3"
- "3.4"
sudo: true

before_install: "sudo apt-get install python-dev libevent-dev"

# command to install dependencies
install: pip install nosetests; python setup.py install
#install: pip install nose gevent>=1.1rc5; python setup.py install
install: "pip install -r pip-requirements.txt; pip install -r pip-requirements-test.txt;"

# command to run tests
script: nosetests
#script: nosetests
script: py.test
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ exclude socketio/.ropeproject/*
exclude socketio/sample_protocol_for_doc.py
recursive-include docs *
recursive-include tests *
include pip-requirements.txt
include pip-requirements-test.txt
11 changes: 11 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,14 @@ If you want to do all of that in a virtualenv, run::
. env/bin/activate
python setup.py develop # or install

To execute all tests, run:

tox

To execute all tests for a specific Python version, run something like:

tox -e py27

To execute a specific test for a specific Python version, run something like:

tox -e py27 -- test_packet.py::TestEncodeMessage::test_encode_event
2 changes: 2 additions & 0 deletions pip-requirements-test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pytest
mock
3 changes: 3 additions & 0 deletions pip-requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
gevent>=1.1rc5
gevent-websocket
six
17 changes: 15 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
import os

from setuptools import setup
from setuptools import find_packages
from setuptools.command.test import test as TestCommand

CURRENT_DIR = os.path.abspath(os.path.dirname(__file__))

def get_reqs(*fns):
lst = []
for fn in fns:
for package in open(os.path.join(CURRENT_DIR, fn)).readlines():
package = package.strip()
if not package:
continue
lst.append(package.strip())
return lst

class PyTest(TestCommand):
def finalize_options(self):
Expand All @@ -27,10 +40,10 @@ def run_tests(self):
license="BSD",
url="https://github.com/abourget/gevent-socketio",
download_url="https://github.com/abourget/gevent-socketio",
install_requires=("gevent", "gevent-websocket",),
install_requires=get_reqs('pip-requirements.txt'),
setup_requires=('versiontools >= 1.7'),
cmdclass = {'test': PyTest},
tests_require=['pytest', 'mock'],
tests_require=get_reqs('pip-requirements-test.txt'),
packages=find_packages(exclude=["examples", "tests"]),
classifiers=[
"Development Status :: 4 - Beta",
Expand Down
1 change: 1 addition & 0 deletions socketio/defaultjson.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ def default(self, o):

def default_json_dumps(data):
return json.dumps(data, separators=(',', ':'),
sort_keys=True,
**json_decimal_args)

def default_json_loads(data):
Expand Down
19 changes: 10 additions & 9 deletions socketio/handler.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import sys
import re
import gevent
import urlparse
from six.moves.urllib.parse import parse_qs

from gevent.pywsgi import WSGIHandler
from socketio import transports


class SocketIOHandler(WSGIHandler):
RE_REQUEST_URL = re.compile(r"""
^/(?P<resource>.+?)
Expand Down Expand Up @@ -45,23 +46,23 @@ def __init__(self, config, *args, **kwargs):

super(SocketIOHandler, self).__init__(*args, **kwargs)

self.transports = self.handler_types.keys()
self.transports = list(self.handler_types.keys())
if self.server.transports:
self.transports = self.server.transports
if not set(self.transports).issubset(set(self.handler_types)):
raise ValueError("transports should be elements of: %s" %
(self.handler_types.keys()))
list(self.handler_types.keys()))

def _do_handshake(self, tokens):
if tokens["resource"] != self.server.resource:
self.log_error("socket.io URL mismatch")
else:
socket = self.server.get_socket()
data = "%s:%s:%s:%s" % (socket.sessid,
self.config['heartbeat_timeout'] or '',
self.config['close_timeout'] or '',
",".join(self.transports))
self.write_smart(data)
self.config['heartbeat_timeout'] or '',
self.config['close_timeout'] or '',
",".join(self.transports))
self.write_smart(data.encode('latin-1'))

def write_jsonp_result(self, data, wrapper="0"):
self.start_response("200 OK", [
Expand All @@ -74,13 +75,13 @@ def write_plain_result(self, data):
("Access-Control-Allow-Origin", self.environ.get('HTTP_ORIGIN', '*')),
("Access-Control-Allow-Credentials", "true"),
("Access-Control-Allow-Methods", "POST, GET, OPTIONS"),
("Access-Control-Max-Age", 3600),
("Access-Control-Max-Age", "3600"),
("Content-Type", "text/plain"),
])
self.result = [data]

def write_smart(self, data):
args = urlparse.parse_qs(self.environ.get("QUERY_STRING"))
args = parse_qs(self.environ.get("QUERY_STRING"))

if "jsonp" in args:
self.write_jsonp_result(data, args["jsonp"][0])
Expand Down
8 changes: 5 additions & 3 deletions socketio/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
You'll likely want to create your own Mixins.
"""

import six


class RoomsMixin(object):
def __init__(self, *args, **kwargs):
Expand All @@ -30,7 +32,7 @@ def emit_to_room(self, room, event, *args):
args=args,
endpoint=self.ns_name)
room_name = self._get_room_name(room)
for sessid, socket in self.socket.server.sockets.iteritems():
for sessid, socket in six.iteritems(self.socket.server.sockets):
if 'rooms' not in socket.session:
continue
if room_name in socket.session['rooms'] and self.socket != socket:
Expand All @@ -55,7 +57,7 @@ def broadcast_event(self, event, *args):
args=args,
endpoint=self.ns_name)

for sessid, socket in self.socket.server.sockets.iteritems():
for sessid, socket in six.iteritems(self.socket.server.sockets):
socket.send_packet(pkt)

def broadcast_event_not_me(self, event, *args):
Expand All @@ -68,6 +70,6 @@ def broadcast_event_not_me(self, event, *args):
args=args,
endpoint=self.ns_name)

for sessid, socket in self.socket.server.sockets.iteritems():
for sessid, socket in six.iteritems(self.socket.server.sockets):
if socket is not self.socket:
socket.send_packet(pkt)
4 changes: 2 additions & 2 deletions socketio/namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,14 @@ def process_packet(self, packet):
elif packet_type == 'ack':
callback = self.socket._pop_ack_callback(packet['ackId'])
if not callback:
print "ERROR: No such callback for ackId %s" % packet['ackId']
print("ERROR: No such callback for ackId %s" % packet['ackId'])
return
return callback(*(packet['args']))
elif packet_type == 'disconnect':
# Force a disconnect on the namespace.
return self.call_method_with_acl('recv_disconnect', packet)
else:
print "Unprocessed packet", packet
print("Unprocessed packet", packet)
# TODO: manage the other packet types: disconnect

def process_event(self, packet):
Expand Down
15 changes: 11 additions & 4 deletions socketio/packet.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import six
from socketio.defaultjson import default_json_dumps, default_json_loads

MSG_TYPES = {
Expand All @@ -12,21 +13,21 @@
'noop': 8,
}

MSG_VALUES = dict((v, k) for k, v in MSG_TYPES.iteritems())
MSG_VALUES = dict((v, k) for k, v in six.iteritems(MSG_TYPES))

ERROR_REASONS = {
'transport not supported': 0,
'client not handshaken': 1,
'unauthorized': 2
}

REASONS_VALUES = dict((v, k) for k, v in ERROR_REASONS.iteritems())
REASONS_VALUES = dict((v, k) for k, v in six.iteritems(ERROR_REASONS))

ERROR_ADVICES = {
'reconnect': 0,
}

ADVICES_VALUES = dict((v, k) for k, v in ERROR_ADVICES.iteritems())
ADVICES_VALUES = dict((v, k) for k, v in six.iteritems(ERROR_ADVICES))

socketio_packet_attributes = ['type', 'name', 'data', 'endpoint', 'args',
'ackId', 'reason', 'advice', 'qs', 'id']
Expand Down Expand Up @@ -107,6 +108,11 @@ def decode(rawstr, json_loads=default_json_loads):
Decode a rawstr packet arriving from the socket into a dict.
"""
decoded_msg = {}
try:
# Handle decoding in Python<3.
rawstr = rawstr.decode('utf-8')
except AttributeError:
pass
split_data = rawstr.split(":", 3)
msg_type = split_data[0]
msg_id = split_data[1]
Expand Down Expand Up @@ -153,7 +159,7 @@ def decode(rawstr, json_loads=default_json_loads):
elif msg_type == "5": # event
try:
data = json_loads(data)
except ValueError, e:
except ValueError:
print("Invalid JSON event message", data)
decoded_msg['args'] = []
else:
Expand Down Expand Up @@ -183,6 +189,7 @@ def decode(rawstr, json_loads=default_json_loads):
decoded_msg['reason'] = REASONS_VALUES[int(data)]
else:
decoded_msg['reason'] = ''

elif msg_type == "8": # noop
pass

Expand Down
8 changes: 7 additions & 1 deletion socketio/sdjango.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
from socketio import socketio_manage
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils.importlib import import_module

try:
# Django versions >= 1.9
from django.utils.module_loading import import_module
except ImportError:
# Django versions < 1.9
from django.utils.importlib import import_module

# for Django 1.3 support
try:
Expand Down
2 changes: 1 addition & 1 deletion socketio/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def start_accepting(self):
try:
if not self.policy_server.started:
self.policy_server.start()
except error, ex:
except error as ex:
sys.stderr.write(
'FAILED to start flash policy server: %s\n' % (ex, ))
except Exception:
Expand Down
14 changes: 8 additions & 6 deletions socketio/transports.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import gevent
import urllib
import urlparse
import six
from six.moves.urllib.parse import parse_qs, unquote_plus
from geventwebsocket import WebSocketError
from gevent.queue import Empty

Expand All @@ -21,7 +21,7 @@ def __init__(self, handler, config, **kwargs):
("Access-Control-Allow-Origin", "*"),
("Access-Control-Allow-Credentials", "true"),
("Access-Control-Allow-Methods", "POST, GET, OPTIONS"),
("Access-Control-Max-Age", 3600),
("Access-Control-Max-Age", "3600"),
]
self.handler = handler
self.config = config
Expand Down Expand Up @@ -162,7 +162,7 @@ def __init__(self, handler, config):
def _request_body(self):
data = super(JSONPolling, self)._request_body()
# resolve %20%3F's, take out wrapping d="...", etc..
data = urllib.unquote_plus(data)[3:-1] \
data = unquote_plus(data)[3:-1] \
.replace(r'\"', '"') \
.replace(r"\\", "\\")

Expand All @@ -175,7 +175,7 @@ def _request_body(self):

def write(self, data):
"""Just quote out stuff before sending it out"""
args = urlparse.parse_qs(self.handler.environ.get("QUERY_STRING"))
args = parse_qs(self.handler.environ.get("QUERY_STRING"))
if "i" in args:
i = args["i"]
else:
Expand Down Expand Up @@ -249,7 +249,9 @@ def send_into_ws():
break
try:
websocket.send(message)
except (WebSocketError, TypeError):
except (WebSocketError, TypeError) as e:
print(e)
raise
# We can't send a message on the socket
# it is dead, let the other sockets know
socket.disconnect()
Expand Down
7 changes: 4 additions & 3 deletions socketio/virtsocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

"""
import random
import six
import weakref
import logging

Expand Down Expand Up @@ -311,7 +312,7 @@ def disconnect(self, silent=False):
:meth:`~socketio.namespace.BaseNamespace.disconnect`
calls.
"""
for ns_name, ns in list(self.active_ns.iteritems()):
for ns_name, ns in list(six.iteritems(self.active_ns)):
ns.recv_disconnect()

def remove_namespace(self, namespace):
Expand Down Expand Up @@ -362,7 +363,7 @@ def _receiver_loop(self):
continue # or close the connection ?
try:
pkt = packet.decode(rawdata, self.json_loads)
except (ValueError, KeyError, Exception), e:
except (ValueError, KeyError, Exception) as e:
self.error('invalid_packet',
"There was a decoding error when dealing with packet "
"with event: %s... (%s)" % (rawdata[:20], e))
Expand Down Expand Up @@ -436,7 +437,7 @@ def _watcher(self):
while True:
gevent.sleep(1.0)
if not self.connected:
for ns_name, ns in list(self.active_ns.iteritems()):
for ns_name, ns in list(six.iteritems(self.active_ns)):
ns.recv_disconnect()
# Killing Socket-level jobs
gevent.killall(self.jobs)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ def test_del_acl_method(self):
except ValueError as e:
self.assertEqual(
message,
e.message,
str(e),
)
else:
raise Exception("""We should not be able to delete an acl that
Expand Down
2 changes: 1 addition & 1 deletion tests/test_packet.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ def test_except_on_invalid_message_type(self):
try:
decoded_message = decode('99::')
except Exception as e:
self.assertEqual(e.message, "Unknown message type: 99")
self.assertEqual(str(e), "Unknown message type: 99")
else:
self.assertEqual(decoded_message, None,
"We should not get a valid message")
Expand Down
Loading