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

Patch WebSocketApp class to make it inheritable #442

Merged
merged 2 commits into from
Aug 14, 2018
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
48 changes: 48 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,54 @@ This example is similar to how WebSocket code looks in browsers using JavaScript
ws.run_forever()


Class inheritance
-----------------
Same as above with class inheritance.

.. code:: python

import websocket
from threading import Thread
import time
import sys


class MyApp(websocket.WebSocketApp):
def on_message(self, message):
print(message)

def on_error(self, error):
print(error)

def on_close(self):
print("### closed ###")

def on_open(self):
def run(*args):
for i in range(3):
# send the message, then wait
# so thread doesn't exit and socket
# isn't closed
self.send("Hello %d" % i)
time.sleep(1)

time.sleep(1)
self.close()
print("Thread terminating...")

Thread(target=run).start()


if __name__ == "__main__":
websocket.enableTrace(True)
if len(sys.argv) < 2:
host = "ws://echo.websocket.org/"
else:
host = sys.argv[1]
ws = MyApp(host)
ws.run_forever()


Short-lived one-off send-receive
--------------------------------
This is if you want to communicate a short message and disconnect immediately when done.
Expand Down
40 changes: 40 additions & 0 deletions examples/echoapp_client_inheritance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import websocket
from threading import Thread
import time
import sys


class MyApp(websocket.WebSocketApp):
def on_message(self, message):
print(message)

def on_error(self, error):
print(error)

def on_close(self):
print("### closed ###")

def on_open(self):
def run(*args):
for i in range(3):
# send the message, then wait
# so thread doesn't exit and socket
# isn't closed
self.send("Hello %d" % i)
time.sleep(1)

time.sleep(1)
self.close()
print("Thread terminating...")

Thread(target=run).start()


if __name__ == "__main__":
websocket.enableTrace(True)
if len(sys.argv) < 2:
host = "ws://echo.websocket.org/"
else:
host = sys.argv[1]
ws = MyApp(host)
ws.run_forever()
25 changes: 15 additions & 10 deletions websocket/_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"""
WebSocketApp provides higher level APIs.
"""
import inspect
import select
import sys
import threading
Expand Down Expand Up @@ -125,16 +126,17 @@ def __init__(self, url, header=None,
self.url = url
self.header = header if header is not None else []
self.cookie = cookie
self.on_open = on_open
self.on_message = on_message
self.on_data = on_data
self.on_error = on_error
self.on_close = on_close
self.on_ping = on_ping
self.on_pong = on_pong
self.on_cont_message = on_cont_message

self.on_open = on_open or getattr(self, 'on_open', None)
self.on_message = on_message or getattr(self, 'on_message', None)
self.on_data = on_data or getattr(self, 'on_data', None)
self.on_error = on_error or getattr(self, 'on_error', None)
self.on_close = on_close or getattr(self, 'on_close', None)
self.on_ping = on_ping or getattr(self, 'on_ping', None)
self.on_pong = on_pong or getattr(self, 'on_pong', None)
self.on_cont_message = on_cont_message or getattr(self, 'on_cont_message', None)
self.get_mask_key = get_mask_key or getattr(self, 'get_mask_key', None)
self.keep_running = False
self.get_mask_key = get_mask_key
self.sock = None
self.last_ping_tm = 0
self.last_pong_tm = 0
Expand Down Expand Up @@ -317,7 +319,10 @@ def _get_close_args(self, data):
def _callback(self, callback, *args):
if callback:
try:
callback(self, *args)
if inspect.ismethod(callback):
callback(*args)
else:
callback(self, *args)
except Exception as e:
_logging.error("error from callback {}: {}".format(callback, e))
if _logging.isEnabledForDebug():
Expand Down
26 changes: 24 additions & 2 deletions websocket/tests/test_websocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,28 @@ def on_open(self, *args, **kwargs):
# Note: We can't use 'is' for comparing the functions directly, need to use 'id'.
# self.assertEqual(WebSocketAppTest.get_mask_key_id, id(my_mask_key_func))

def testSettingClassCallbacks(self):
""" App class should provide possibility to set callback functions via class instantiate call, class inheritance
and via setting instance attributes
"""
class TestApp(ws.WebSocketApp):
def on_close(self):
pass

def on_open(ws):
pass

def on_message(ws):
pass

app = TestApp('ws://www.example.com/', on_open=on_open)
app.on_message = on_message

#assert isinstance(app.on_close, function)
assert callable(app.on_open)
assert callable(app.on_message)
assert callable(app.on_close)


class SockOptTest(unittest.TestCase):
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are disabled")
Expand All @@ -551,6 +573,7 @@ def testSockOpt(self):
self.assertNotEqual(s.sock.getsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY), 0)
s.close()


class UtilsTest(unittest.TestCase):
def testUtf8Validator(self):
state = validate_utf8(six.b('\xf0\x90\x80\x80'))
Expand All @@ -560,6 +583,7 @@ def testUtf8Validator(self):
state = validate_utf8(six.b(''))
self.assertEqual(state, True)


class ProxyInfoTest(unittest.TestCase):
def setUp(self):
self.http_proxy = os.environ.get("http_proxy", None)
Expand All @@ -580,7 +604,6 @@ def tearDown(self):
elif "https_proxy" in os.environ:
del os.environ["https_proxy"]


def testProxyFromArgs(self):
self.assertEqual(get_proxy_info("echo.websocket.org", False, proxy_host="localhost"), ("localhost", 0, None))
self.assertEqual(get_proxy_info("echo.websocket.org", False, proxy_host="localhost", proxy_port=3128), ("localhost", 3128, None))
Expand All @@ -601,7 +624,6 @@ def testProxyFromArgs(self):
self.assertEqual(get_proxy_info("echo.websocket.org", True, proxy_host="localhost", proxy_port=3128, no_proxy=["echo.websocket.org"], proxy_auth=("a", "b")),
(None, 0, None))


def testProxyFromEnv(self):
os.environ["http_proxy"] = "http://localhost/"
self.assertEqual(get_proxy_info("echo.websocket.org", False), ("localhost", None, None))
Expand Down