Skip to content

Commit

Permalink
Merge pull request #236 from chrisspen/master
Browse files Browse the repository at this point in the history
Fixed import to support Django>=1.9.
  • Loading branch information
kennedyshead committed Mar 14, 2016
2 parents 1c84627 + a76b50e commit 8971328
Show file tree
Hide file tree
Showing 19 changed files with 108 additions and 36 deletions.
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

0 comments on commit 8971328

Please sign in to comment.