Hello community, here is the log from the commit of package python-websocket-client for openSUSE:Factory checked in at 2016-12-08 00:30:34 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-websocket-client (Old) and /work/SRC/openSUSE:Factory/.python-websocket-client.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-websocket-client" Changes: -------- --- /work/SRC/openSUSE:Factory/python-websocket-client/python-websocket-client.changes 2016-04-28 16:56:45.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.python-websocket-client.new/python-websocket-client.changes 2016-12-08 00:30:35.000000000 +0100 @@ -1,0 +2,31 @@ +Tue Nov 15 13:11:34 UTC 2016 - dmuel...@suse.com + +- update to 0.37.0: + - fixed fialer that `websocket.create_connection` does not accept `origin` as a parameter (#246 ) + - added support for using custom connection class (#235) + - use Named logger (#238) + - implement ping/pong timeout (#241) + - Corrects the syntax highlight code (#243) + - fixed failure to join thread before it is started (#242) + - Prints timings in console (#217) + - use inspect.getfullargspec with Python 3.x (#219) + - Check that exception message is actually a string before trying for substring check (#224) + - Use pre-initialized stream socket (#226) + - fixed TypeError: cafile, capath and cadata cannot be all omitted (#227) + - Change import style (#203) + - fix attribute error on the older python. (#215) + - fixed timeout+ssl error handling bug on python 2.7.10 (#190) + - add proxy support to wsdump.py (#194) + - use wsaccel if available (#193) + - add support for ssl cert chains to support client certs (#195) + - fix string formatting in exception (#196) + - fix typo in README.rst (#197) + - introduce on_data callback to pass data type. (#198) + - WebSocketBadStatusException for Handshake error (#199) + - set close timeout (#192) + - Map dict to headers list (#204) + - support client certification (#207) + - security improvement during handshake (#211) + - improve logging of error from callback (#212) + +------------------------------------------------------------------- Old: ---- websocket_client-0.32.0.tar.gz New: ---- websocket_client-0.37.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-websocket-client.spec ++++++ --- /var/tmp/diff_new_pack.IK3PVt/_old 2016-12-08 00:30:36.000000000 +0100 +++ /var/tmp/diff_new_pack.IK3PVt/_new 2016-12-08 00:30:36.000000000 +0100 @@ -24,13 +24,13 @@ %endif Name: python-websocket-client -Version: 0.32.0 +Version: 0.37.0 Release: 0 Summary: WebSocket client implementation License: LGPL-2.1 Group: Development/Languages/Python Url: https://github.com/liris/websocket-client/releases -Source0: https://pypi.python.org/packages/source/w/websocket-client/websocket_client-%{version}.tar.gz +Source0: https://pypi.io/packages/source/w/websocket-client/websocket_client-%{version}.tar.gz BuildRequires: %backports BuildRequires: python-setuptools BuildRequires: python-six @@ -90,7 +90,6 @@ update-alternatives --remove wsdump.py %{_bindir}/wsdump.py-%{py_ver} fi - %files %defattr(-,root,root,-) %doc LICENSE README.rst ++++++ websocket_client-0.32.0.tar.gz -> websocket_client-0.37.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/ChangeLog new/websocket_client-0.37.0/ChangeLog --- old/websocket_client-0.32.0/ChangeLog 2015-06-03 02:44:39.000000000 +0200 +++ new/websocket_client-0.37.0/ChangeLog 2016-04-14 02:27:00.000000000 +0200 @@ -1,6 +1,44 @@ ChangeLog ============ +- 0.37.0 + - fixed fialer that `websocket.create_connection` does not accept `origin` as a parameter (#246 ) + +- 0.36.0 + - added support for using custom connection class (#235) + - use Named logger (#238) + - implement ping/pong timeout (#241) + - Corrects the syntax highlight code (#243) + - fixed failure to join thread before it is started (#242) + +- 0.35.0 + - Prints timings in console (#217) + - use inspect.getfullargspec with Python 3.x (#219) + - Check that exception message is actually a string before trying for substring check (#224) + - Use pre-initialized stream socket (#226) + - fixed TypeError: cafile, capath and cadata cannot be all omitted (#227) + +- 0.34.0 + + - Change import style (#203) + - fix attribute error on the older python. (#215) + +- 0.33.0 + + - fixed timeout+ssl error handling bug on python 2.7.10 (#190) + - add proxy support to wsdump.py (#194) + - use wsaccel if available (#193) + - add support for ssl cert chains to support client certs (#195) + - fix string formatting in exception (#196) + - fix typo in README.rst (#197) + - introduce on_data callback to pass data type. (#198) + - WebSocketBadStatusException for Handshake error (#199) + - set close timeout (#192) + - Map dict to headers list (#204) + - support client certification (#207) + - security improvement during handshake (#211) + - improve logging of error from callback (#212) + - 0.32.0 - fix http proxy bug (#189) @@ -35,7 +73,7 @@ - remove unittest2 requirements for python 2.6 (#156) - fixed subprotocol case during header validation (#158) - get response status and headers (#160) - - fix out-of-memory due to fragmentation when recieving a very large frame(#163) + - fix out-of-memory due to fragmentation when receiving a very large frame(#163) - fix error if the payload data is nothing.(#166) - refactoring. @@ -64,7 +102,7 @@ - Fix not thread-safe of Websocket.close() (#120) - Try to get proxy info from environment if not explicitly provided (#124) - - support proxy basic authenticaiton. (#125) + - support proxy basic authentication. (#125) - Fix NoneType exception at WebsocketApp.send (#126) - not use proxy for localhost (#132) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/PKG-INFO new/websocket_client-0.37.0/PKG-INFO --- old/websocket_client-0.32.0/PKG-INFO 2015-06-03 02:45:15.000000000 +0200 +++ new/websocket_client-0.37.0/PKG-INFO 2016-04-14 02:27:29.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: websocket_client -Version: 0.32.0 +Version: 0.37.0 Summary: WebSocket client for python. hybi13 is supported. Home-page: https://github.com/liris/websocket-client Author: liris @@ -51,7 +51,9 @@ Current implementation of websocket-client is using "CONNECT" method via proxy. - example:: + example + + .. code:: python import websocket ws = websocket.WebSocket() @@ -63,28 +65,49 @@ Example ============= - Low Level API example:: + Low Level API example + + .. code:: python from websocket import create_connection ws = create_connection("ws://echo.websocket.org/") print "Sending 'Hello, World'..." ws.send("Hello, World") print "Sent" - print "Reeiving..." + print "Receiving..." result = ws.recv() print "Received '%s'" % result ws.close() If you want to customize socket options, set sockopt. - sockopt example:: + sockopt example + + .. code:: python from websocket import create_connection ws = create_connection("ws://echo.websocket.org/", sockopt=((socket.IPPROTO_TCP, socket.TCP_NODELAY),)) + You can also use your own class for the connection. + + custom connection class example + + ..code:: python + + from websocket import create_connection, WebSocket + class MyWebSocket(WebSocket): + def recv_frame(self): + frame = super().recv_frame() + print('yay! I got this frame: ', frame) + return frame + + ws = create_connection("ws://echo.websocket.org/", + sockopt=((socket.IPPROTO_TCP, socket.TCP_NODELAY),), class_=MyWebSocket) + + JavaScript websocket-like API example - JavaScript websocket-like API example:: + .. code:: python import websocket import thread @@ -128,17 +151,23 @@ Please set sslopt to {"cert_reqs": ssl.CERT_NONE}. - WebSocketApp sample:: + WebSocketApp sample + + .. code:: python ws = websocket.WebSocketApp("wss://echo.websocket.org") ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE}) - create_connection sample:: + create_connection sample + + .. code:: python ws = websocket.create_connection("wss://echo.websocket.org", sslopt={"cert_reqs": ssl.CERT_NONE}) - WebSocket sample:: + WebSocket sample + + .. code:: python ws = websocket.WebSocket(sslopt={"cert_reqs": ssl.CERT_NONE}) ws.connect("wss://echo.websocket.org") @@ -150,24 +179,30 @@ Please set sslopt to {"check_hostname": False}. (since v0.18.0) - WebSocketApp sample:: + WebSocketApp sample + + .. code:: python ws = websocket.WebSocketApp("wss://echo.websocket.org") ws.run_forever(sslopt={"check_hostname": False}) - create_connection sample:: + create_connection sample + + .. code:: python ws = websocket.create_connection("wss://echo.websocket.org", sslopt={"check_hostname": False}) - WebSocket sample:: + WebSocket sample + + .. code:: python ws = websocket.WebSocket(sslopt={"check_hostname": False}) ws.connect("wss://echo.websocket.org") How to enable `SNI <http://en.wikipedia.org/wiki/Server_Name_Indication>`_? - ------------------ + --------------------------------------------------------------------------- SNI support is available for Python 2.7.9+ and 3.2+. It will be enabled automatically whenever possible. @@ -175,10 +210,12 @@ Sub Protocols. ---------------------------------------- - The server needs to support sub protocols, please set the subprotcol like this. + The server needs to support sub protocols, please set the subprotocol like this. + + Subprotocol sample - Subprotocol sample:: + .. code:: python ws = websocket.create_connection("ws://exapmle.com/websocket", subprotocols=["binary", "base64"]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/README.rst new/websocket_client-0.37.0/README.rst --- old/websocket_client-0.32.0/README.rst 2015-04-28 02:10:55.000000000 +0200 +++ new/websocket_client-0.37.0/README.rst 2016-04-12 01:43:10.000000000 +0200 @@ -43,7 +43,9 @@ Current implementation of websocket-client is using "CONNECT" method via proxy. -example:: +example + +.. code:: python import websocket ws = websocket.WebSocket() @@ -55,28 +57,49 @@ Example ============= -Low Level API example:: +Low Level API example + +.. code:: python from websocket import create_connection ws = create_connection("ws://echo.websocket.org/") print "Sending 'Hello, World'..." ws.send("Hello, World") print "Sent" - print "Reeiving..." + print "Receiving..." result = ws.recv() print "Received '%s'" % result ws.close() If you want to customize socket options, set sockopt. -sockopt example:: +sockopt example + +.. code:: python from websocket import create_connection ws = create_connection("ws://echo.websocket.org/", sockopt=((socket.IPPROTO_TCP, socket.TCP_NODELAY),)) +You can also use your own class for the connection. + +custom connection class example + +..code:: python + + from websocket import create_connection, WebSocket + class MyWebSocket(WebSocket): + def recv_frame(self): + frame = super().recv_frame() + print('yay! I got this frame: ', frame) + return frame + + ws = create_connection("ws://echo.websocket.org/", + sockopt=((socket.IPPROTO_TCP, socket.TCP_NODELAY),), class_=MyWebSocket) + +JavaScript websocket-like API example -JavaScript websocket-like API example:: +.. code:: python import websocket import thread @@ -120,17 +143,23 @@ Please set sslopt to {"cert_reqs": ssl.CERT_NONE}. -WebSocketApp sample:: +WebSocketApp sample + +.. code:: python ws = websocket.WebSocketApp("wss://echo.websocket.org") ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE}) -create_connection sample:: +create_connection sample + +.. code:: python ws = websocket.create_connection("wss://echo.websocket.org", sslopt={"cert_reqs": ssl.CERT_NONE}) -WebSocket sample:: +WebSocket sample + +.. code:: python ws = websocket.WebSocket(sslopt={"cert_reqs": ssl.CERT_NONE}) ws.connect("wss://echo.websocket.org") @@ -142,24 +171,30 @@ Please set sslopt to {"check_hostname": False}. (since v0.18.0) -WebSocketApp sample:: +WebSocketApp sample + +.. code:: python ws = websocket.WebSocketApp("wss://echo.websocket.org") ws.run_forever(sslopt={"check_hostname": False}) -create_connection sample:: +create_connection sample + +.. code:: python ws = websocket.create_connection("wss://echo.websocket.org", sslopt={"check_hostname": False}) -WebSocket sample:: +WebSocket sample + +.. code:: python ws = websocket.WebSocket(sslopt={"check_hostname": False}) ws.connect("wss://echo.websocket.org") How to enable `SNI <http://en.wikipedia.org/wiki/Server_Name_Indication>`_? ------------------- +--------------------------------------------------------------------------- SNI support is available for Python 2.7.9+ and 3.2+. It will be enabled automatically whenever possible. @@ -167,10 +202,12 @@ Sub Protocols. ---------------------------------------- -The server needs to support sub protocols, please set the subprotcol like this. +The server needs to support sub protocols, please set the subprotocol like this. + +Subprotocol sample -Subprotocol sample:: +.. code:: python ws = websocket.create_connection("ws://exapmle.com/websocket", subprotocols=["binary", "base64"]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/bin/wsdump.py new/websocket_client-0.37.0/bin/wsdump.py --- old/websocket_client-0.32.0/bin/wsdump.py 2015-05-22 04:01:33.000000000 +0200 +++ new/websocket_client-0.37.0/bin/wsdump.py 2016-01-04 07:13:49.000000000 +0100 @@ -7,6 +7,7 @@ import threading import time import websocket +from six.moves.urllib.parse import urlparse try: import readline except: @@ -39,6 +40,8 @@ parser = argparse.ArgumentParser(description="WebSocket Simple Dump Tool") parser.add_argument("url", metavar="ws_url", help="websocket url. ex. ws://echo.websocket.org/") + parser.add_argument("-p", "--proxy", + help="proxy url. ex. http://127.0.0.1:8080") parser.add_argument("-v", "--verbose", default=0, nargs='?', action=VAction, dest="verbose", help="set verbose mode. If set to 1, show opcode. " @@ -52,9 +55,11 @@ parser.add_argument("-o", "--origin", help="Set origin") parser.add_argument("--eof-wait", default=0, type=int, - help="wait time(second) after 'EOF' recieved.") + help="wait time(second) after 'EOF' received.") parser.add_argument("-t", "--text", help="Send initial text") + parser.add_argument("--timings", action="store_true", + help="Print timings in seconds") return parser.parse_args() @@ -93,10 +98,15 @@ return self.raw_input("") def main(): + start_time = time.time() args = parse_args() if args.verbose > 1: websocket.enableTrace(True) options = {} + if (args.proxy): + p = urlparse(args.proxy) + options["http_proxy_host"] = p.hostname + options["http_proxy_port"] = p.port if (args.origin): options["origin"] = args.origin if (args.subprotocols): @@ -142,7 +152,10 @@ msg = "%s: %s" % (websocket.ABNF.OPCODE_MAP.get(opcode), data) if msg is not None: - console.write(msg) + if (args.timings): + console.write(str(time.time() - start_time) + ": " + msg) + else: + console.write(msg) if opcode == websocket.ABNF.OPCODE_CLOSE: break diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/examples/echoapp_client.py new/websocket_client-0.37.0/examples/echoapp_client.py --- old/websocket_client-0.32.0/examples/echoapp_client.py 2014-12-03 00:17:56.000000000 +0100 +++ new/websocket_client-0.37.0/examples/echoapp_client.py 2016-01-04 07:13:49.000000000 +0100 @@ -23,8 +23,8 @@ def run(*args): for i in range(3): # send the message, then wait - # so thread doesnt exit and socket - # isnt closed + # so thread doesn't exit and socket + # isn't closed ws.send("Hello %d" % i) time.sleep(1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/setup.py new/websocket_client-0.37.0/setup.py --- old/websocket_client-0.32.0/setup.py 2015-06-03 02:44:39.000000000 +0200 +++ new/websocket_client-0.37.0/setup.py 2016-04-14 02:10:56.000000000 +0200 @@ -1,7 +1,7 @@ from setuptools import setup import sys -VERSION = "0.32.0" +VERSION = "0.37.0" NAME="websocket_client" install_requires = ["six"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/websocket/__init__.py new/websocket_client-0.37.0/websocket/__init__.py --- old/websocket_client-0.32.0/websocket/__init__.py 2015-06-03 02:44:39.000000000 +0200 +++ new/websocket_client-0.37.0/websocket/__init__.py 2016-04-14 02:11:13.000000000 +0200 @@ -22,4 +22,4 @@ from ._core import * from ._app import WebSocketApp -__version__ = "0.32.0" +__version__ = "0.37.0" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/websocket/_abnf.py new/websocket_client-0.37.0/websocket/_abnf.py --- old/websocket_client-0.32.0/websocket/_abnf.py 2015-04-01 00:47:57.000000000 +0200 +++ new/websocket_client-0.37.0/websocket/_abnf.py 2016-01-04 07:13:49.000000000 +0100 @@ -26,6 +26,24 @@ from ._exceptions import * from ._utils import validate_utf8 +try: + # If wsaccel is available we use compiled routines to mask data. + from wsaccel.xormask import XorMaskerSimple + + def _mask(_m, _d): + return XorMaskerSimple(_m).process(_d) + +except ImportError: + # wsaccel is not available, we rely on python implementations. + def _mask(_m, _d): + for i in range(len(_d)): + _d[i] ^= _m[i % 4] + + if six.PY3: + return _d.tobytes() + else: + return _d.tostring() + # closing frame status codes. STATUS_NORMAL = 1000 STATUS_GOING_AWAY = 1001 @@ -81,7 +99,7 @@ OPCODE_PONG: "pong" } - # data length threashold. + # data length threshold. LENGTH_7 = 0x7e LENGTH_16 = 1 << 16 LENGTH_63 = 1 << 63 @@ -144,8 +162,8 @@ create frame to send text, binary and other data. data: data to send. This is string value(byte array). - if opcode is OPCODE_TEXT and this value is uniocde, - data value is conveted into unicode string, automatically. + if opcode is OPCODE_TEXT and this value is unicode, + data value is converted into unicode string, automatically. opcode: operation code. please see OPCODE_XXX. @@ -208,6 +226,7 @@ """ if data == None: data = "" + if isinstance(mask_key, six.text_type): mask_key = six.b(mask_key) @@ -216,14 +235,7 @@ _m = array.array("B", mask_key) _d = array.array("B", data) - for i in range(len(_d)): - _d[i] ^= _m[i % 4] - - if six.PY3: - return _d.tobytes() - else: - return _d.tostring() - + return _mask(_m, _d) class frame_buffer(object): _HEADER_MASK_INDEX = 5 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/websocket/_app.py new/websocket_client-0.37.0/websocket/_app.py --- old/websocket_client-0.32.0/websocket/_app.py 2015-04-28 02:10:55.000000000 +0200 +++ new/websocket_client-0.37.0/websocket/_app.py 2016-04-12 01:58:13.000000000 +0200 @@ -33,7 +33,7 @@ from ._core import WebSocket, getdefaulttimeout from ._exceptions import * from ._logging import * -from websocket._abnf import ABNF +from ._abnf import ABNF __all__ = ["WebSocketApp"] @@ -48,29 +48,38 @@ on_close=None, on_ping=None, on_pong=None, on_cont_message=None, keep_running=True, get_mask_key=None, cookie=None, - subprotocols=None): + subprotocols=None, + on_data=None): """ url: websocket url. header: custom header for websocket handshake. on_open: callable object which is called at opening websocket. - this function has one argument. The arugment is this class object. - on_message: callbale object which is called when recieved data. + this function has one argument. The argument is this class object. + on_message: callable object which is called when received data. on_message has 2 arguments. - The 1st arugment is this class object. - The passing 2nd arugment is utf-8 string which we get from the server. + The 1st argument is this class object. + The 2nd argument is utf-8 string which we get from the server. on_error: callable object which is called when we get error. on_error has 2 arguments. - The 1st arugment is this class object. - The passing 2nd arugment is exception object. + The 1st argument is this class object. + The 2nd argument is exception object. on_close: callable object which is called when closed the connection. - this function has one argument. The arugment is this class object. - on_cont_message: callback object which is called when recieve continued + this function has one argument. The argument is this class object. + on_cont_message: callback object which is called when receive continued frame data. - on_message has 3 arguments. - The 1st arugment is this class object. - The passing 2nd arugment is utf-8 string which we get from the server. - The 3rd arugment is continue flag. if 0, the data continue + on_cont_message has 3 arguments. + The 1st argument is this class object. + The 2nd argument is utf-8 string which we get from the server. + The 3rd argument is continue flag. if 0, the data continue to next frame data + on_data: callback object which is called when a message received. + This is called before on_message or on_cont_message, + and then on_message or on_cont_message is called. + on_data has 4 argument. + The 1st argument is this class object. + The 2nd argument is utf-8 string which we get from the server. + The 3rd argument is data type. ABNF.OPCODE_TEXT or ABNF.OPCODE_BINARY will be came. + The 4th argument is continue flag. if 0, the data continue keep_running: a boolean flag indicating whether the app's main loop should keep running, defaults to True get_mask_key: a callable to produce new mask keys, @@ -82,6 +91,7 @@ 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 @@ -91,6 +101,7 @@ self.get_mask_key = get_mask_key self.sock = None self.last_ping_tm = 0 + self.last_pong_tm = 0 self.subprotocols = subprotocols def send(self, data, opcode=ABNF.OPCODE_TEXT): @@ -129,12 +140,12 @@ This loop is infinite loop and is alive during websocket is available. sockopt: values for socket.setsockopt. sockopt must be tuple - and each element is argument of sock.setscokopt. + and each element is argument of sock.setsockopt. sslopt: ssl socket optional dict. ping_interval: automatically send "ping" command every specified period(second) if set to 0, not send automatically. - ping_timeout: timeout(second) if the pong message is not recieved. + ping_timeout: timeout(second) if the pong message is not received. http_proxy_host: http proxy host name. http_proxy_port: http proxy port. If not set, set to 80. http_no_proxy: host names, which doesn't use proxy. @@ -145,6 +156,8 @@ if not ping_timeout or ping_timeout <= 0: ping_timeout = None + if ping_timeout and ping_interval and ping_interval <= ping_timeout: + raise WebSocketException("Ensure ping_interval > ping_timeout") if sockopt is None: sockopt = [] if sslopt is None: @@ -178,9 +191,6 @@ r, w, e = select.select((self.sock.sock, ), (), (), ping_timeout) if not self.keep_running: break - if ping_timeout and self.last_ping_tm and time.time() - self.last_ping_tm > ping_timeout: - self.last_ping_tm = 0 - raise WebSocketTimeoutException("ping timed out") if r: op_code, frame = self.sock.recv_data_frame(True) @@ -190,18 +200,29 @@ elif op_code == ABNF.OPCODE_PING: self._callback(self.on_ping, frame.data) elif op_code == ABNF.OPCODE_PONG: + self.last_pong_tm = time.time() self._callback(self.on_pong, frame.data) elif op_code == ABNF.OPCODE_CONT and self.on_cont_message: + self._callback(self.on_data, data, frame.opcode, frame.fin) self._callback(self.on_cont_message, frame.data, frame.fin) else: data = frame.data if six.PY3 and frame.opcode == ABNF.OPCODE_TEXT: data = data.decode("utf-8") + self._callback(self.on_data, data, frame.opcode, True) self._callback(self.on_message, data) - except Exception as e: + + if ping_timeout and self.last_ping_tm \ + and self.last_ping_tm - time.time() > ping_timeout \ + and self.last_ping_tm - self.last_pong_tm > ping_timeout: + raise WebSocketTimeoutException("ping/pong timed out") + except (Exception, KeyboardInterrupt, SystemExit) as e: self._callback(self.on_error, e) + if isinstance(e, SystemExit): + # propagate SystemExit further + raise finally: - if thread: + if thread and thread.isAlive(): event.set() thread.join() self.keep_running = False @@ -215,8 +236,12 @@ if they exists, and if the self.on_close except three arguments """ import inspect # if the on_close callback is "old", just return empty list - if not self.on_close or len(inspect.getargspec(self.on_close).args) != 3: - return [] + if sys.version_info < (3, 0): + if not self.on_close or len(inspect.getargspec(self.on_close).args) != 3: + return [] + else: + if not self.on_close or len(inspect.getfullargspec(self.on_close).args) != 3: + return [] if data and len(data) >= 2: code = 256*six.byte2int(data[0:1]) + six.byte2int(data[1:2]) @@ -230,7 +255,7 @@ try: callback(self, *args) except Exception as e: - error(e) + error("error from callback {}: {}".format(callback, e)) if isEnabledForDebug(): _, _, tb = sys.exc_info() traceback.print_tb(tb) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/websocket/_core.py new/websocket_client-0.37.0/websocket/_core.py --- old/websocket_client-0.32.0/websocket/_core.py 2015-04-28 02:10:55.000000000 +0200 +++ new/websocket_client-0.37.0/websocket/_core.py 2016-04-14 02:24:17.000000000 +0200 @@ -53,58 +53,6 @@ """ -def create_connection(url, timeout=None, **options): - """ - connect to url and return websocket object. - - Connect to url and return the WebSocket object. - Passing optional timeout parameter will set the timeout on the socket. - If no timeout is supplied, - the global default timeout setting returned by getdefauttimeout() is used. - You can customize using 'options'. - If you set "header" list object, you can set your own custom header. - - >>> conn = create_connection("ws://echo.websocket.org/", - ... header=["User-Agent: MyProgram", - ... "x-custom: header"]) - - - timeout: socket timeout time. This value is integer. - if you set None for this value, - it means "use default_timeout value" - - - options: "header" -> custom http header list. - "cookie" -> cookie value. - "origin" -> custom origin url. - "host" -> custom host header string. - "http_proxy_host" - http proxy host name. - "http_proxy_port" - http proxy port. If not set, set to 80. - "http_no_proxy" - host names, which doesn't use proxy. - "http_proxy_auth" - http proxy auth infomation. - tuple of username and password. - default is None - "enable_multithread" -> enable lock for multithread. - "sockopt" -> socket options - "sslopt" -> ssl option - "subprotocols" - array of available sub protocols. - default is None. - "skip_utf8_validation" - skip utf8 validation. - """ - sockopt = options.get("sockopt", []) - sslopt = options.get("sslopt", {}) - fire_cont_frame = options.get("fire_cont_frame", False) - enable_multithread = options.get("enable_multithread", False) - skip_utf8_validation = options.get("skip_utf8_validation", False) - websock = WebSocket(sockopt=sockopt, sslopt=sslopt, - fire_cont_frame=fire_cont_frame, - enable_multithread=enable_multithread, - skip_utf8_validation=skip_utf8_validation) - websock.settimeout(timeout if timeout is not None else getdefaulttimeout()) - websock.connect(url, **options) - return websock - - class WebSocket(object): """ Low level WebSocket interface. @@ -112,8 +60,8 @@ The WebSocket protocol draft-hixie-thewebsocketprotocol-76 http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76 - We can connect to the websocket server and send/recieve data. - The following example is a echo client. + We can connect to the websocket server and send/receive data. + The following example is an echo client. >>> import websocket >>> ws = websocket.WebSocket() @@ -126,7 +74,7 @@ get_mask_key: a callable to produce new mask keys, see the set_mask_key function's docstring for more details sockopt: values for socket.setsockopt. - sockopt must be tuple and each element is argument of sock.setscokopt. + sockopt must be tuple and each element is argument of sock.setsockopt. sslopt: dict object for ssl socket option. fire_cont_frame: fire recv event for each cont frame. default is False enable_multithread: if set to True, lock send method. @@ -135,9 +83,9 @@ def __init__(self, get_mask_key=None, sockopt=None, sslopt=None, fire_cont_frame=False, enable_multithread=False, - skip_utf8_validation=False): + skip_utf8_validation=False, **options): """ - Initalize WebSocket object. + Initialize WebSocket object. """ self.sock_opt = sock_opt(sockopt, sslopt) self.handshake_response = None @@ -172,12 +120,12 @@ def set_mask_key(self, func): """ - set function to create musk key. You can custumize mask key generator. + set function to create musk key. You can customize mask key generator. Mainly, this is for testing purpose. - func: callable object. the fuct must 1 argument as integer. + func: callable object. the func takes 1 argument as integer. The argument means length of mask key. - This func must be return string(byte array), + This func must return string(byte array), which length is argument specified. """ self.get_mask_key = func @@ -249,21 +197,23 @@ if you set None for this value, it means "use default_timeout value" - options: "header" -> custom http header list. + options: "header" -> custom http header list or dict. "cookie" -> cookie value. "origin" -> custom origin url. "host" -> custom host header string. "http_proxy_host" - http proxy host name. "http_proxy_port" - http proxy port. If not set, set to 80. "http_no_proxy" - host names, which doesn't use proxy. - "http_proxy_auth" - http proxy auth infomation. + "http_proxy_auth" - http proxy auth information. tuple of username and password. - defualt is None + default is None "subprotocols" - array of available sub protocols. default is None. + "socket" - pre-initialized stream socket. """ - self.sock, addrs = connect(url, self.sock_opt, proxy_info(**options)) + self.sock, addrs = connect(url, self.sock_opt, proxy_info(**options), + options.pop('socket', None)) try: self.handshake_response = handshake(self.sock, *addrs, **options) @@ -355,7 +305,7 @@ def recv_data(self, control_frame=False): """ - Recieve data with operation code. + Receive data with operation code. control_frame: a boolean flag indicating whether to return control frame data, defaults to False @@ -367,7 +317,7 @@ def recv_data_frame(self, control_frame=False): """ - Recieve data with operation code. + Receive data with operation code. control_frame: a boolean flag indicating whether to return control frame data, defaults to False @@ -403,7 +353,7 @@ def recv_frame(self): """ - recieve data as frame from server. + receive data as frame from server. return value: ABNF frame object. """ @@ -422,13 +372,16 @@ self.connected = False self.send(struct.pack('!H', status) + reason, ABNF.OPCODE_CLOSE) - def close(self, status=STATUS_NORMAL, reason=six.b("")): + def close(self, status=STATUS_NORMAL, reason=six.b(""), timeout=3): """ Close Websocket object status: status code to send. see STATUS_XXX. reason: the reason to close. This must be string. + + timeout: timeout until receive a close frame. + If None, it will wait forever until receive a close frame. """ if self.connected: if status < 0 or status >= ABNF.LENGTH_16: @@ -437,8 +390,8 @@ try: self.connected = False self.send(struct.pack('!H', status) + reason, ABNF.OPCODE_CLOSE) - timeout = self.sock.gettimeout() - self.sock.settimeout(3) + sock_timeout = self.sock.gettimeout() + self.sock.settimeout(timeout) try: frame = self.recv_frame() if isEnabledForError(): @@ -447,7 +400,7 @@ error("close status: " + repr(recv_status)) except: pass - self.sock.settimeout(timeout) + self.sock.settimeout(sock_timeout) self.sock.shutdown(socket.SHUT_RDWR) except: pass @@ -456,7 +409,7 @@ def abort(self): """ - Low-level asynchonous abort, wakes up other threads that are waiting in recv_* + Low-level asynchronous abort, wakes up other threads that are waiting in recv_* """ if self.connected: self.sock.shutdown(socket.SHUT_RDWR) @@ -480,3 +433,58 @@ self.sock = None self.connected = False raise + + +def create_connection(url, timeout=None, class_=WebSocket, **options): + """ + connect to url and return websocket object. + + Connect to url and return the WebSocket object. + Passing optional timeout parameter will set the timeout on the socket. + If no timeout is supplied, + the global default timeout setting returned by getdefauttimeout() is used. + You can customize using 'options'. + If you set "header" list object, you can set your own custom header. + + >>> conn = create_connection("ws://echo.websocket.org/", + ... header=["User-Agent: MyProgram", + ... "x-custom: header"]) + + + timeout: socket timeout time. This value is integer. + if you set None for this value, + it means "use default_timeout value" + + class_: class to instantiate when creating the connection. It has to implement + settimeout and connect. It's __init__ should be compatible with + WebSocket.__init__, i.e. accept all of it's kwargs. + options: "header" -> custom http header list or dict. + "cookie" -> cookie value. + "origin" -> custom origin url. + "host" -> custom host header string. + "http_proxy_host" - http proxy host name. + "http_proxy_port" - http proxy port. If not set, set to 80. + "http_no_proxy" - host names, which doesn't use proxy. + "http_proxy_auth" - http proxy auth information. + tuple of username and password. + default is None + "enable_multithread" -> enable lock for multithread. + "sockopt" -> socket options + "sslopt" -> ssl option + "subprotocols" - array of available sub protocols. + default is None. + "skip_utf8_validation" - skip utf8 validation. + "socket" - pre-initialized stream socket. + """ + sockopt = options.pop("sockopt", []) + sslopt = options.pop("sslopt", {}) + fire_cont_frame = options.pop("fire_cont_frame", False) + enable_multithread = options.pop("enable_multithread", False) + skip_utf8_validation = options.pop("skip_utf8_validation", False) + websock = class_(sockopt=sockopt, sslopt=sslopt, + fire_cont_frame=fire_cont_frame, + enable_multithread=enable_multithread, + skip_utf8_validation=skip_utf8_validation, **options) + websock.settimeout(timeout if timeout is not None else getdefaulttimeout()) + websock.connect(url, **options) + return websock diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/websocket/_exceptions.py new/websocket_client-0.37.0/websocket/_exceptions.py --- old/websocket_client-0.32.0/websocket/_exceptions.py 2015-03-10 07:36:38.000000000 +0100 +++ new/websocket_client-0.37.0/websocket/_exceptions.py 2016-01-04 07:13:49.000000000 +0100 @@ -27,22 +27,25 @@ class WebSocketException(Exception): """ - websocket exeception class. + websocket exception class. """ pass + class WebSocketProtocolException(WebSocketException): """ - If the webscoket protocol is invalid, this exception will be raised. + If the websocket protocol is invalid, this exception will be raised. """ pass + class WebSocketPayloadException(WebSocketException): """ - If the webscoket payload is invalid, this exception will be raised. + If the websocket payload is invalid, this exception will be raised. """ pass + class WebSocketConnectionClosedException(WebSocketException): """ If remote host closed the connection or some network error happened, @@ -50,16 +53,25 @@ """ pass + class WebSocketTimeoutException(WebSocketException): """ WebSocketTimeoutException will be raised at socket timeout during read/write data. """ pass + class WebSocketProxyException(WebSocketException): """ - WebSocketProxyException will be raised when proxy error occured. + WebSocketProxyException will be raised when proxy error occurred. """ pass +class WebSocketBadStatusException(WebSocketException): + """ + WebSocketBadStatusException will be raised when we get bad handshake status code. + """ + def __init__(self, message, status_code): + super(WebSocketBadStatusException, self).__init__(message % status_code) + self.status_code = status_code diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/websocket/_handshake.py new/websocket_client-0.37.0/websocket/_handshake.py --- old/websocket_client-0.32.0/websocket/_handshake.py 2015-05-22 04:01:33.000000000 +0200 +++ new/websocket_client-0.37.0/websocket/_handshake.py 2015-10-28 01:16:18.000000000 +0100 @@ -28,6 +28,9 @@ import uuid import hashlib +import hmac +import os +import sys from ._logging import * from ._url import * @@ -37,6 +40,12 @@ __all__ = ["handshake_response", "handshake"] +if hasattr(hmac, "compare_digest"): + compare_digest = hmac.compare_digest +else: + def compare_digest(s1, s2): + return s1 == s2 + # websocket supported version. VERSION = 13 @@ -92,7 +101,10 @@ headers.append("Sec-WebSocket-Protocol: %s" % ",".join(subprotocols)) if "header" in options: - headers.extend(options["header"]) + header = options["header"] + if isinstance(header, dict): + header = map(": ".join, header.items()) + headers.extend(header) cookie = options.get("cookie", None) @@ -108,7 +120,7 @@ def _get_resp_headers(sock, success_status=101): status, resp_headers = read_headers(sock) if status != success_status: - raise WebSocketException("Handshake status %d" % status) + raise WebSocketBadStatusException("Handshake status %d", status) return status, resp_headers _HEADERS_TO_CHECK = { @@ -143,7 +155,8 @@ value = (key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").encode('utf-8') hashed = base64encode(hashlib.sha1(value).digest()).strip().lower() - success = (hashed == result) + success = compare_digest(hashed, result) + if success: return True, subproto else: @@ -151,5 +164,5 @@ def _create_sec_websocket_key(): - uid = uuid.uuid4() - return base64encode(uid.bytes).decode('utf-8').strip() + randomness = os.urandom(16) + return base64encode(randomness).decode('utf-8').strip() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/websocket/_http.py new/websocket_client-0.37.0/websocket/_http.py --- old/websocket_client-0.32.0/websocket/_http.py 2015-06-03 02:44:39.000000000 +0200 +++ new/websocket_client-0.37.0/websocket/_http.py 2016-01-04 09:02:13.000000000 +0100 @@ -51,8 +51,12 @@ self.auth = None self.no_proxy = None -def connect(url, options, proxy): +def connect(url, options, proxy, socket): hostname, port, resource, is_secure = parse_url(url) + + if socket: + return socket, (hostname, port, resource) + addrinfo_list, need_tunnel, auth = _get_addrinfo_list(hostname, port, is_secure, proxy) if not addrinfo_list: raise WebSocketException( @@ -119,19 +123,29 @@ def _can_use_sni(): - return (six.PY2 and sys.version_info[1] >= 7 and sys.version_info[2] >= 9) or (six.PY3 and sys.version_info[2] >= 2) + return six.PY2 and sys.version_info >= (2, 7, 9) or sys.version_info >= (3, 2) def _wrap_sni_socket(sock, sslopt, hostname, check_hostname): context = ssl.SSLContext(sslopt.get('ssl_version', ssl.PROTOCOL_SSLv23)) - context.load_verify_locations(cafile=sslopt.get('ca_certs', None)) + if sslopt.get('cert_reqs', ssl.CERT_NONE) != ssl.CERT_NONE: + context.load_verify_locations(cafile=sslopt.get('ca_certs', None)) + if sslopt.get('certfile', None): + context.load_cert_chain( + sslopt['certfile'], + sslopt.get('keyfile', None), + sslopt.get('password', None), + ) # see https://github.com/liris/websocket-client/commit/b96a2e8fa765753e82eea531adb19716b52ca3ca#commitcomment-10803153 context.verify_mode = sslopt['cert_reqs'] if HAVE_CONTEXT_CHECK_HOSTNAME: context.check_hostname = check_hostname if 'ciphers' in sslopt: context.set_ciphers(sslopt['ciphers']) + if 'cert_chain' in sslopt : + certfile,keyfile,password = sslopt['cert_chain'] + context.load_cert_chain(certfile, keyfile, password) return context.wrap_socket( sock, @@ -143,11 +157,12 @@ def _ssl_socket(sock, user_sslopt, hostname): sslopt = dict(cert_reqs=ssl.CERT_REQUIRED) + sslopt.update(user_sslopt) + certPath = os.path.join( os.path.dirname(__file__), "cacert.pem") - if os.path.isfile(certPath): + if os.path.isfile(certPath) and user_sslopt.get('ca_certs', None) == None: sslopt['ca_certs'] = certPath - sslopt.update(user_sslopt) check_hostname = sslopt["cert_reqs"] != ssl.CERT_NONE and sslopt.pop('check_hostname', True) if _can_use_sni(): @@ -183,7 +198,7 @@ if status != 200: raise WebSocketProxyException( - "failed CONNECT via proxy status: %r" + status) + "failed CONNECT via proxy status: %r" % status) return sock diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/websocket/_logging.py new/websocket_client-0.37.0/websocket/_logging.py --- old/websocket_client-0.32.0/websocket/_logging.py 2015-04-28 02:10:55.000000000 +0200 +++ new/websocket_client-0.37.0/websocket/_logging.py 2016-04-12 01:43:10.000000000 +0200 @@ -22,7 +22,7 @@ import logging -_logger = logging.getLogger() +_logger = logging.getLogger('websocket') _traceEnabled = False __all__ = ["enableTrace", "dump", "error", "debug", "trace", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/websocket/_socket.py new/websocket_client-0.37.0/websocket/_socket.py --- old/websocket_client-0.32.0/websocket/_socket.py 2015-04-01 00:47:57.000000000 +0200 +++ new/websocket_client-0.37.0/websocket/_socket.py 2016-01-04 07:17:01.000000000 +0100 @@ -115,7 +115,7 @@ raise WebSocketTimeoutException(message) except Exception as e: message = extract_err_message(e) - if message and "timed out" in message: + if isinstance(message, str) and "timed out" in message: raise WebSocketTimeoutException(message) else: raise diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/websocket/_url.py new/websocket_client-0.37.0/websocket/_url.py --- old/websocket_client-0.32.0/websocket/_url.py 2015-04-01 00:47:57.000000000 +0200 +++ new/websocket_client-0.37.0/websocket/_url.py 2016-01-04 07:13:49.000000000 +0100 @@ -100,9 +100,9 @@ options: "http_proxy_host" - http proxy host name. "http_proxy_port" - http proxy port. "http_no_proxy" - host names, which doesn't use proxy. - "http_proxy_auth" - http proxy auth infomation. + "http_proxy_auth" - http proxy auth information. tuple of username and password. - defualt is None + default is None """ if _is_no_proxy_host(hostname, no_proxy): return None, 0, None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/websocket/_utils.py new/websocket_client-0.37.0/websocket/_utils.py --- old/websocket_client-0.32.0/websocket/_utils.py 2015-05-22 04:01:33.000000000 +0200 +++ new/websocket_client-0.37.0/websocket/_utils.py 2016-01-04 07:13:49.000000000 +0100 @@ -28,43 +28,63 @@ def __enter__(self): pass - def __exit__(self,type, value, traceback): + def __exit__(self, type, value, traceback): pass +try: + # If wsaccel is available we use compiled routines to validate UTF-8 + # strings. + from wsaccel.utf8validator import Utf8Validator + + def _validate_utf8(utfbytes): + return Utf8Validator().validate(utfbytes)[0] + +except ImportError: + # UTF-8 validator + # python implementation of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ + + _UTF8_ACCEPT = 0 + _UTF8_REJECT = 12 + + _UTF8D = [ + # The first part of the table maps bytes to character classes that + # to reduce the size of the transition table and create bitmasks. + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + + # The second part is a transition table that maps a combination + # of a state of the automaton and a character class to a state. + 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, + 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, + 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, + 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, + 12,36,12,12,12,12,12,12,12,12,12,12, ] + + def _decode(state, codep, ch): + tp = _UTF8D[ch] + + codep = (ch & 0x3f ) | (codep << 6) if (state != _UTF8_ACCEPT) else (0xff >> tp) & (ch) + state = _UTF8D[256 + state + tp] + + return state, codep; + + def _validate_utf8(utfbytes): + state = _UTF8_ACCEPT + codep = 0 + for i in utfbytes: + if six.PY2: + i = ord(i) + state, codep = _decode(state, codep, i) + if state == _UTF8_REJECT: + return False -# UTF-8 validator -# python implementation of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ - -UTF8_ACCEPT = 0 -UTF8_REJECT=12 - -_UTF8D = [ - # The first part of the table maps bytes to character classes that - # to reduce the size of the transition table and create bitmasks. - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, - - # The second part is a transition table that maps a combination - # of a state of the automaton and a character class to a state. - 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, - 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, - 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, - 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, - 12,36,12,12,12,12,12,12,12,12,12,12, ] - -def _decode(state, codep, ch): - tp = _UTF8D[ch] - - codep = (ch & 0x3f ) | (codep << 6) if (state != UTF8_ACCEPT) else (0xff >> tp) & (ch) - state = _UTF8D[256 + state + tp] - - return state, codep; + return True def validate_utf8(utfbytes): """ @@ -72,17 +92,10 @@ utfbytes: utf byte string to check. return value: if valid utf8 string, return true. Otherwise, return false. """ - state = UTF8_ACCEPT - codep = 0 - for i in utfbytes: - if six.PY2: - i = ord(i) - state, codep = _decode(state, codep, i) - if state == UTF8_REJECT: - return False - - return True - + return _validate_utf8(utfbytes) def extract_err_message(exception): - return getattr(exception, 'strerror', str(exception)) + if exception.args: + return exception.args[0] + else: + return None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/websocket/tests/test_websocket.py new/websocket_client-0.37.0/websocket/tests/test_websocket.py --- old/websocket_client-0.32.0/websocket/tests/test_websocket.py 2015-05-22 04:01:33.000000000 +0200 +++ new/websocket_client-0.37.0/websocket/tests/test_websocket.py 2015-10-27 07:48:24.000000000 +0100 @@ -464,12 +464,12 @@ self.assertRaises(ws.WebSocketConnectionClosedException, s.send, "Hello") self.assertRaises(ws.WebSocketConnectionClosedException, s.recv) - def testUUID4(self): - """ WebSocket key should be a UUID4. + def testNonce(self): + """ WebSocket key should be a random 16-byte nonce. """ key = _create_sec_websocket_key() - u = uuid.UUID(bytes=base64decode(key.encode("utf-8"))) - self.assertEqual(4, u.version) + nonce = base64decode(key.encode("utf-8")) + self.assertEqual(16, len(nonce)) class WebSocketAppTest(unittest.TestCase): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/websocket_client.egg-info/PKG-INFO new/websocket_client-0.37.0/websocket_client.egg-info/PKG-INFO --- old/websocket_client-0.32.0/websocket_client.egg-info/PKG-INFO 2015-06-03 02:45:13.000000000 +0200 +++ new/websocket_client-0.37.0/websocket_client.egg-info/PKG-INFO 2016-04-14 02:27:29.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: websocket-client -Version: 0.32.0 +Version: 0.37.0 Summary: WebSocket client for python. hybi13 is supported. Home-page: https://github.com/liris/websocket-client Author: liris @@ -51,7 +51,9 @@ Current implementation of websocket-client is using "CONNECT" method via proxy. - example:: + example + + .. code:: python import websocket ws = websocket.WebSocket() @@ -63,28 +65,49 @@ Example ============= - Low Level API example:: + Low Level API example + + .. code:: python from websocket import create_connection ws = create_connection("ws://echo.websocket.org/") print "Sending 'Hello, World'..." ws.send("Hello, World") print "Sent" - print "Reeiving..." + print "Receiving..." result = ws.recv() print "Received '%s'" % result ws.close() If you want to customize socket options, set sockopt. - sockopt example:: + sockopt example + + .. code:: python from websocket import create_connection ws = create_connection("ws://echo.websocket.org/", sockopt=((socket.IPPROTO_TCP, socket.TCP_NODELAY),)) + You can also use your own class for the connection. + + custom connection class example + + ..code:: python + + from websocket import create_connection, WebSocket + class MyWebSocket(WebSocket): + def recv_frame(self): + frame = super().recv_frame() + print('yay! I got this frame: ', frame) + return frame + + ws = create_connection("ws://echo.websocket.org/", + sockopt=((socket.IPPROTO_TCP, socket.TCP_NODELAY),), class_=MyWebSocket) + + JavaScript websocket-like API example - JavaScript websocket-like API example:: + .. code:: python import websocket import thread @@ -128,17 +151,23 @@ Please set sslopt to {"cert_reqs": ssl.CERT_NONE}. - WebSocketApp sample:: + WebSocketApp sample + + .. code:: python ws = websocket.WebSocketApp("wss://echo.websocket.org") ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE}) - create_connection sample:: + create_connection sample + + .. code:: python ws = websocket.create_connection("wss://echo.websocket.org", sslopt={"cert_reqs": ssl.CERT_NONE}) - WebSocket sample:: + WebSocket sample + + .. code:: python ws = websocket.WebSocket(sslopt={"cert_reqs": ssl.CERT_NONE}) ws.connect("wss://echo.websocket.org") @@ -150,24 +179,30 @@ Please set sslopt to {"check_hostname": False}. (since v0.18.0) - WebSocketApp sample:: + WebSocketApp sample + + .. code:: python ws = websocket.WebSocketApp("wss://echo.websocket.org") ws.run_forever(sslopt={"check_hostname": False}) - create_connection sample:: + create_connection sample + + .. code:: python ws = websocket.create_connection("wss://echo.websocket.org", sslopt={"check_hostname": False}) - WebSocket sample:: + WebSocket sample + + .. code:: python ws = websocket.WebSocket(sslopt={"check_hostname": False}) ws.connect("wss://echo.websocket.org") How to enable `SNI <http://en.wikipedia.org/wiki/Server_Name_Indication>`_? - ------------------ + --------------------------------------------------------------------------- SNI support is available for Python 2.7.9+ and 3.2+. It will be enabled automatically whenever possible. @@ -175,10 +210,12 @@ Sub Protocols. ---------------------------------------- - The server needs to support sub protocols, please set the subprotcol like this. + The server needs to support sub protocols, please set the subprotocol like this. + + Subprotocol sample - Subprotocol sample:: + .. code:: python ws = websocket.create_connection("ws://exapmle.com/websocket", subprotocols=["binary", "base64"]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/websocket_client-0.32.0/websocket_client.egg-info/requires.txt new/websocket_client-0.37.0/websocket_client.egg-info/requires.txt --- old/websocket_client-0.32.0/websocket_client.egg-info/requires.txt 2015-06-03 02:45:13.000000000 +0200 +++ new/websocket_client-0.37.0/websocket_client.egg-info/requires.txt 2016-04-14 02:27:29.000000000 +0200 @@ -1 +1,2 @@ -six \ No newline at end of file +six +backports.ssl_match_hostname