Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-websocket-client for
openSUSE:Factory checked in at 2023-05-11 12:31:35
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-websocket-client (Old)
and /work/SRC/openSUSE:Factory/.python-websocket-client.new.1533 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-websocket-client"
Thu May 11 12:31:35 2023 rev:21 rq:1085984 version:1.5.1
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-websocket-client/python-websocket-client.changes
2023-04-25 16:53:24.674146958 +0200
+++
/work/SRC/openSUSE:Factory/.python-websocket-client.new.1533/python-websocket-client.changes
2023-05-11 12:31:41.162172237 +0200
@@ -1,0 +2,12 @@
+Wed May 10 07:00:29 UTC 2023 - Dirk Müller <[email protected]>
+
+- update to 1.5.1:
+ * Fix logic bug that can cause disconnects
+ * Refactor and improve ping/pong logic to resolve several
+ issues, including an infinite loop issue during reconnect
+ * Fix issue where `skip_utf8_validation = True` is ignored
+ * Fix issue where sslopt `is_ssl` is ignored
+ * Downgrade "websocket connected" message from logging.warning
+ to logging.info
+
+-------------------------------------------------------------------
Old:
----
websocket-client-1.4.2.tar.gz
New:
----
websocket-client-1.5.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-websocket-client.spec ++++++
--- /var/tmp/diff_new_pack.8A70VM/_old 2023-05-11 12:31:41.670174734 +0200
+++ /var/tmp/diff_new_pack.8A70VM/_new 2023-05-11 12:31:41.674174753 +0200
@@ -22,11 +22,9 @@
%bcond_with libalternatives
%endif
-%{?!python_module:%define python_module() python-%{**} python3-%{**}}
-%define skip_python2 1
%{?sle15_python_module_pythons}
Name: python-websocket-client
-Version: 1.4.2
+Version: 1.5.1
Release: 0
Summary: WebSocket client implementation
License: LGPL-2.1-only
++++++ websocket-client-1.4.2.tar.gz -> websocket-client-1.5.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/websocket-client-1.4.2/ChangeLog
new/websocket-client-1.5.1/ChangeLog
--- old/websocket-client-1.4.2/ChangeLog 2022-11-04 05:01:44.000000000
+0100
+++ new/websocket-client-1.5.1/ChangeLog 2023-02-04 18:55:28.000000000
+0100
@@ -1,6 +1,16 @@
ChangeLog
============
+- 1.5.1
+ - Fix logic bug that can cause disconnects (#893)
+
+- 1.5.0
+ - Refactor and improve ping/pong logic to resolve several issues, including
an infinite loop issue during reconnect (#862)
+ - Fix issue where `skip_utf8_validation = True` is ignored (#886)
+ - Fix issue where sslopt `is_ssl` is ignored (#875)
+ - Downgrade "websocket connected" message from logging.warning to
logging.info (#888)
+ - Update github actions to newer versions (669fe1b)
+
- 1.4.2
- create_dispatcher is determined by URL ws/wss, NOT by presence of sslopt
args, to maintain consistency (#875)
- Remove redundant key generation line (#864)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/websocket-client-1.4.2/PKG-INFO
new/websocket-client-1.5.1/PKG-INFO
--- old/websocket-client-1.4.2/PKG-INFO 2022-11-04 05:02:49.798043000 +0100
+++ new/websocket-client-1.5.1/PKG-INFO 2023-02-04 18:58:33.128578000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: websocket-client
-Version: 1.4.2
+Version: 1.5.1
Summary: WebSocket client for Python with low level API options
Home-page: https://github.com/websocket-client/websocket-client.git
Download-URL: https://github.com/websocket-client/websocket-client/releases
@@ -113,9 +113,10 @@
`run_forever` provides a variety of event-based connection controls
using callbacks like `on_message` and `on_error`.
-`run_forever` does not automatically reconnect if the server
+`run_forever` **does not automatically reconnect** if the server
closes the WebSocket gracefully (returning
[a standard websocket close
code](https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1)).
+[This is the
logic](https://github.com/websocket-client/websocket-client/pull/838#issuecomment-1228454826)
behind the decision.
Customizing behavior when the server closes
the WebSocket should be handled in the `on_close` callback.
This example uses [rel](https://github.com/bubbleboy14/registeredeventlistener)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/websocket-client-1.4.2/README.md
new/websocket-client-1.5.1/README.md
--- old/websocket-client-1.4.2/README.md 2022-10-26 03:38:57.000000000
+0200
+++ new/websocket-client-1.5.1/README.md 2023-02-04 18:51:20.000000000
+0100
@@ -80,9 +80,10 @@
`run_forever` provides a variety of event-based connection controls
using callbacks like `on_message` and `on_error`.
-`run_forever` does not automatically reconnect if the server
+`run_forever` **does not automatically reconnect** if the server
closes the WebSocket gracefully (returning
[a standard websocket close
code](https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1)).
+[This is the
logic](https://github.com/websocket-client/websocket-client/pull/838#issuecomment-1228454826)
behind the decision.
Customizing behavior when the server closes
the WebSocket should be handled in the `on_close` callback.
This example uses [rel](https://github.com/bubbleboy14/registeredeventlistener)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/websocket-client-1.4.2/setup.py
new/websocket-client-1.5.1/setup.py
--- old/websocket-client-1.4.2/setup.py 2022-11-04 04:57:54.000000000 +0100
+++ new/websocket-client-1.5.1/setup.py 2023-02-04 18:54:19.000000000 +0100
@@ -21,7 +21,7 @@
limitations under the License.
"""
-VERSION = "1.4.2"
+VERSION = "1.5.1"
install_requires = []
tests_require = []
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/websocket-client-1.4.2/websocket/__init__.py
new/websocket-client-1.5.1/websocket/__init__.py
--- old/websocket-client-1.4.2/websocket/__init__.py 2022-11-04
04:58:05.000000000 +0100
+++ new/websocket-client-1.5.1/websocket/__init__.py 2023-02-04
18:54:12.000000000 +0100
@@ -23,4 +23,4 @@
from ._logging import *
from ._socket import *
-__version__ = "1.4.2"
+__version__ = "1.5.1"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/websocket-client-1.4.2/websocket/_app.py
new/websocket-client-1.5.1/websocket/_app.py
--- old/websocket-client-1.4.2/websocket/_app.py 2022-11-04
04:51:47.000000000 +0100
+++ new/websocket-client-1.5.1/websocket/_app.py 2023-02-04
18:51:20.000000000 +0100
@@ -4,11 +4,12 @@
import threading
import time
import traceback
+
+from . import _logging
from ._abnf import ABNF
from ._url import parse_url
from ._core import WebSocket, getdefaulttimeout
from ._exceptions import *
-from . import _logging
"""
_app.py
@@ -53,10 +54,9 @@
def reconnect(self, seconds, reconnector):
try:
- while True:
- _logging.info("reconnect() - retrying in %s seconds [%s frames
in stack]" % (seconds, len(inspect.stack())))
- time.sleep(seconds)
- reconnector(reconnecting=True)
+ _logging.info("reconnect() - retrying in %s seconds [%s frames in
stack]" % (seconds, len(inspect.stack())))
+ time.sleep(seconds)
+ reconnector(reconnecting=True)
except KeyboardInterrupt as e:
_logging.info("User exited %s" % (e,))
@@ -214,6 +214,11 @@
self.sock = None
self.last_ping_tm = 0
self.last_pong_tm = 0
+ self.ping_thread = None
+ self.stop_ping = None
+ self.ping_interval = 0
+ self.ping_timeout = None
+ self.ping_payload = ""
self.subprotocols = subprotocols
self.prepared_socket = socket
self.has_errored = False
@@ -244,15 +249,31 @@
self.sock.close(**kwargs)
self.sock = None
- def _send_ping(self, interval, event, payload):
- while not event.wait(interval):
- self.last_ping_tm = time.time()
+ def _start_ping_thread(self):
+ self.last_ping_tm = self.last_pong_tm = 0
+ self.stop_ping = threading.Event()
+ self.ping_thread = threading.Thread(target=self._send_ping)
+ self.ping_thread.daemon = True
+ self.ping_thread.start()
+
+ def _stop_ping_thread(self):
+ if self.stop_ping:
+ self.stop_ping.set()
+ if self.ping_thread and self.ping_thread.is_alive():
+ self.ping_thread.join(3)
+ self.last_ping_tm = self.last_pong_tm = 0
+
+ def _send_ping(self):
+ if self.stop_ping.wait(self.ping_interval):
+ return
+ while not self.stop_ping.wait(self.ping_interval):
if self.sock:
+ self.last_ping_tm = time.time()
try:
- self.sock.ping(payload)
+ _logging.debug("Sending ping")
+ self.sock.ping(self.ping_payload)
except Exception as ex:
- _logging.warning("send_ping routine terminated:
{}".format(ex))
- break
+ _logging.debug("Failed to send ping: %s", ex)
def run_forever(self, sockopt=None, sslopt=None,
ping_interval=0, ping_timeout=None,
@@ -331,10 +352,11 @@
sslopt = {}
if self.sock:
raise WebSocketException("socket is already opened")
- thread = None
+
+ self.ping_interval = ping_interval
+ self.ping_timeout = ping_timeout
+ self.ping_payload = ping_payload
self.keep_running = True
- self.last_ping_tm = 0
- self.last_pong_tm = 0
def teardown(close_frame=None):
"""
@@ -347,9 +369,7 @@
with the statusCode and reason from the provided frame.
"""
- if thread and thread.is_alive():
- event.set()
- thread.join()
+ self._stop_ping_thread()
self.keep_running = False
if self.sock:
self.sock.close()
@@ -361,11 +381,15 @@
self._callback(self.on_close, close_status_code, close_reason)
def setSock(reconnecting=False):
+ if reconnecting and self.sock:
+ self.sock.shutdown()
+
self.sock = WebSocket(
self.get_mask_key, sockopt=sockopt, sslopt=sslopt,
fire_cont_frame=self.on_cont_message is not None,
skip_utf8_validation=skip_utf8_validation,
enable_multithread=True)
+
self.sock.settimeout(getdefaulttimeout())
try:
self.sock.connect(
@@ -377,13 +401,16 @@
host=host, origin=origin, suppress_origin=suppress_origin,
proxy_type=proxy_type, socket=self.prepared_socket)
+ _logging.info("Websocket connected")
+
+ if self.ping_interval:
+ self._start_ping_thread()
+
self._callback(self.on_open)
- _logging.warning("websocket connected")
dispatcher.read(self.sock.sock, read, check)
except (WebSocketConnectionClosedException,
ConnectionRefusedError, KeyboardInterrupt, SystemExit, Exception) as e:
- _logging.error("%s - %s" % (e, reconnect and "reconnecting" or
"goodbye"))
- reconnecting or handleDisconnect(e)
+ handleDisconnect(e, reconnecting)
def read():
if not self.keep_running:
@@ -396,6 +423,7 @@
return handleDisconnect(e)
else:
raise e
+
if op_code == ABNF.OPCODE_CLOSE:
return teardown(frame)
elif op_code == ABNF.OPCODE_PING:
@@ -410,7 +438,7 @@
frame.data, frame.fin)
else:
data = frame.data
- if op_code == ABNF.OPCODE_TEXT:
+ if op_code == ABNF.OPCODE_TEXT and not skip_utf8_validation:
data = data.decode("utf-8")
self._callback(self.on_data, data, frame.opcode, True)
self._callback(self.on_message, data)
@@ -418,10 +446,10 @@
return True
def check():
- if (ping_timeout):
- has_timeout_expired = time.time() - self.last_ping_tm >
ping_timeout
+ if (self.ping_timeout):
+ has_timeout_expired = time.time() - self.last_ping_tm >
self.ping_timeout
has_pong_not_arrived_after_last_ping = self.last_pong_tm -
self.last_ping_tm < 0
- has_pong_arrived_too_late = self.last_pong_tm -
self.last_ping_tm > ping_timeout
+ has_pong_arrived_too_late = self.last_pong_tm -
self.last_ping_tm > self.ping_timeout
if (self.last_ping_tm and
has_timeout_expired and
@@ -429,29 +457,35 @@
raise WebSocketTimeoutException("ping/pong timed out")
return True
- def handleDisconnect(e):
+ def handleDisconnect(e, reconnecting=False):
self.has_errored = True
- self._callback(self.on_error, e)
- if isinstance(e, SystemExit):
- # propagate SystemExit further
+ self._stop_ping_thread()
+ if not reconnecting:
+ self._callback(self.on_error, e)
+
+ if isinstance(e, (KeyboardInterrupt, SystemExit)):
+ teardown()
+ # Propagate further
raise
- if reconnect and not isinstance(e, KeyboardInterrupt):
- _logging.info("websocket disconnected (retrying in %s seconds)
[%s frames in stack]" % (reconnect, len(inspect.stack())))
- dispatcher.reconnect(reconnect, setSock)
+
+ if reconnect:
+ _logging.info("%s - reconnect" % e)
+ if custom_dispatcher:
+ _logging.debug("Calling custom dispatcher reconnect [%s
frames in stack]" % len(inspect.stack()))
+ dispatcher.reconnect(reconnect, setSock)
else:
+ _logging.error("%s - goodbye" % e)
teardown()
custom_dispatcher = bool(dispatcher)
dispatcher = self.create_dispatcher(ping_timeout, dispatcher,
parse_url(self.url)[3])
- if ping_interval:
- event = threading.Event()
- thread = threading.Thread(
- target=self._send_ping, args=(ping_interval, event,
ping_payload))
- thread.daemon = True
- thread.start()
-
setSock()
+ if not custom_dispatcher and reconnect:
+ while self.keep_running:
+ _logging.debug("Calling dispatcher reconnect [%s frames in
stack]" % len(inspect.stack()))
+ dispatcher.reconnect(reconnect, setSock)
+
return self.has_errored
def create_dispatcher(self, ping_timeout, dispatcher=None, is_ssl=False):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/websocket-client-1.4.2/websocket/_socket.py
new/websocket-client-1.5.1/websocket/_socket.py
--- old/websocket-client-1.4.2/websocket/_socket.py 2022-10-26
03:38:57.000000000 +0200
+++ new/websocket-client-1.5.1/websocket/_socket.py 2023-02-04
18:52:14.000000000 +0100
@@ -151,7 +151,7 @@
error_code = extract_error_code(exc)
if error_code is None:
raise
- if error_code != errno.EAGAIN or error_code != errno.EWOULDBLOCK:
+ if error_code != errno.EAGAIN and error_code != errno.EWOULDBLOCK:
raise
sel = selectors.DefaultSelector()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/websocket-client-1.4.2/websocket/tests/test_app.py
new/websocket-client-1.5.1/websocket/tests/test_app.py
--- old/websocket-client-1.4.2/websocket/tests/test_app.py 2022-11-04
04:51:47.000000000 +0100
+++ new/websocket-client-1.5.1/websocket/tests/test_app.py 2023-02-04
18:51:20.000000000 +0100
@@ -186,13 +186,13 @@
app = ws.WebSocketApp('wss://tsock.us1.twilio.com/v3/wsconnect')
app.run_forever(ping_interval=2, ping_timeout=1, ping_payload="Ping
payload")
- @unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are
disabled")
- def testOpcodeBinary(self):
- """ Test WebSocketApp binary opcode
- """
- # The lack of wss:// in the URL below is on purpose
- app = ws.WebSocketApp('wss://streaming.vn.teslamotors.com/streaming/')
- app.run_forever(ping_interval=2, ping_timeout=1, ping_payload="Ping
payload")
+ # This is commented out because the URL no longer responds in the expected
way
+ # @unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are
disabled")
+ # def testOpcodeBinary(self):
+ # """ Test WebSocketApp binary opcode
+ # """
+ # app =
ws.WebSocketApp('wss://streaming.vn.teslamotors.com/streaming/')
+ # app.run_forever(ping_interval=2, ping_timeout=1, ping_payload="Ping
payload")
@unittest.skipUnless(TEST_WITH_INTERNET, "Internet-requiring tests are
disabled")
def testBadPingInterval(self):
@@ -228,6 +228,91 @@
self.assertRaises(ws.WebSocketConnectionClosedException, app.send,
data="test if connection is closed")
+ @unittest.skipUnless(TEST_WITH_LOCAL_SERVER, "Tests using local websocket
server are disabled")
+ def testCallbackFunctionException(self):
+ """ Test callback function exception handling """
+
+ exc = None
+ passed_app = None
+
+ def on_open(app):
+ raise RuntimeError("Callback failed")
+
+ def on_error(app, err):
+ nonlocal passed_app
+ passed_app = app
+ nonlocal exc
+ exc = err
+
+ def on_pong(app, msg):
+ app.close()
+
+ app = ws.WebSocketApp('ws://127.0.0.1:' + LOCAL_WS_SERVER_PORT,
on_open=on_open, on_error=on_error, on_pong=on_pong)
+ app.run_forever(ping_interval=2, ping_timeout=1)
+
+ self.assertEqual(passed_app, app)
+ self.assertIsInstance(exc, RuntimeError)
+ self.assertEqual(str(exc), "Callback failed")
+
+ @unittest.skipUnless(TEST_WITH_LOCAL_SERVER, "Tests using local websocket
server are disabled")
+ def testCallbackMethodException(self):
+ """ Test callback method exception handling """
+
+ class Callbacks:
+ def __init__(self):
+ self.exc = None
+ self.passed_app = None
+ self.app = ws.WebSocketApp(
+ 'ws://127.0.0.1:' + LOCAL_WS_SERVER_PORT,
+ on_open=self.on_open,
+ on_error=self.on_error,
+ on_pong=self.on_pong
+ )
+ self.app.run_forever(ping_interval=2, ping_timeout=1)
+
+ def on_open(self, app):
+ raise RuntimeError("Callback failed")
+
+ def on_error(self, app, err):
+ self.passed_app = app
+ self.exc = err
+
+ def on_pong(self, app, msg):
+ app.close()
+
+ callbacks = Callbacks()
+
+ self.assertEqual(callbacks.passed_app, callbacks.app)
+ self.assertIsInstance(callbacks.exc, RuntimeError)
+ self.assertEqual(str(callbacks.exc), "Callback failed")
+
+ @unittest.skipUnless(TEST_WITH_LOCAL_SERVER, "Tests using local websocket
server are disabled")
+ def testReconnect(self):
+ """ Test reconnect """
+ pong_count = 0
+ exc = None
+
+ def on_error(app, err):
+ nonlocal exc
+ exc = err
+
+ def on_pong(app, msg):
+ nonlocal pong_count
+ pong_count += 1
+ if pong_count == 1:
+ # First pong, shutdown socket, enforce read error
+ app.sock.shutdown()
+ if pong_count >= 2:
+ # Got second pong after reconnect
+ app.close()
+
+ app = ws.WebSocketApp('ws://127.0.0.1:' + LOCAL_WS_SERVER_PORT,
on_pong=on_pong, on_error=on_error)
+ app.run_forever(ping_interval=2, ping_timeout=1, reconnect=3)
+
+ self.assertEqual(pong_count, 2)
+ self.assertIsInstance(exc, ValueError)
+ self.assertEqual(str(exc), "Invalid file object: None")
+
if __name__ == "__main__":
unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/websocket-client-1.4.2/websocket_client.egg-info/PKG-INFO
new/websocket-client-1.5.1/websocket_client.egg-info/PKG-INFO
--- old/websocket-client-1.4.2/websocket_client.egg-info/PKG-INFO
2022-11-04 05:02:49.000000000 +0100
+++ new/websocket-client-1.5.1/websocket_client.egg-info/PKG-INFO
2023-02-04 18:58:33.000000000 +0100
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: websocket-client
-Version: 1.4.2
+Version: 1.5.1
Summary: WebSocket client for Python with low level API options
Home-page: https://github.com/websocket-client/websocket-client.git
Download-URL: https://github.com/websocket-client/websocket-client/releases
@@ -113,9 +113,10 @@
`run_forever` provides a variety of event-based connection controls
using callbacks like `on_message` and `on_error`.
-`run_forever` does not automatically reconnect if the server
+`run_forever` **does not automatically reconnect** if the server
closes the WebSocket gracefully (returning
[a standard websocket close
code](https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1)).
+[This is the
logic](https://github.com/websocket-client/websocket-client/pull/838#issuecomment-1228454826)
behind the decision.
Customizing behavior when the server closes
the WebSocket should be handled in the `on_close` callback.
This example uses [rel](https://github.com/bubbleboy14/registeredeventlistener)