summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbubbleboy14 <mario.balibrera@gmail.com>2023-01-20 13:14:23 -0800
committerbubbleboy14 <mario.balibrera@gmail.com>2023-01-20 13:14:23 -0800
commitbe4110c08c5d10b52410c36c72d1deb9e4cbf32c (patch)
treed6dddc00338bc416ba72e7de629dd170270ddb8f
parent7d83cc3e559526ca2d6774768baffc19ff14f8da (diff)
parent601a9022d6044bf6d414fdb1122916b65dc58ca7 (diff)
downloadwebsocket-client-t858.tar.gz
Merge branch 'master' into t858t858
-rw-r--r--.github/workflows/build.yml2
-rw-r--r--.github/workflows/codecoverage.yml2
-rw-r--r--.github/workflows/doctest.yml4
-rw-r--r--.github/workflows/lint.yml2
-rw-r--r--ChangeLog5
-rw-r--r--README.md15
-rw-r--r--docs/source/conf.py2
-rw-r--r--docs/source/examples.rst4
-rw-r--r--docs/source/getting_started.rst3
-rw-r--r--docs/source/threading.rst2
-rw-r--r--setup.py3
-rw-r--r--websocket/__init__.py2
-rw-r--r--websocket/_app.py15
-rw-r--r--websocket/_core.py11
-rw-r--r--websocket/_handshake.py1
-rw-r--r--websocket/tests/test_app.py2
-rw-r--r--websocket/tests/test_websocket.py2
17 files changed, 48 insertions, 29 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index ab0e495..490cac3 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -8,7 +8,7 @@ jobs:
strategy:
matrix:
- python-version: ['3.7', '3.8', '3.9', '3.10']
+ python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
os: [ubuntu-latest]
steps:
- name: Check out source repository
diff --git a/.github/workflows/codecoverage.yml b/.github/workflows/codecoverage.yml
index 1b7e103..fe357e7 100644
--- a/.github/workflows/codecoverage.yml
+++ b/.github/workflows/codecoverage.yml
@@ -51,4 +51,4 @@ jobs:
LOCAL_WS_SERVER_PORT: 8765
WEBSOCKET_CLIENT_CA_BUNDLE: "/usr/lib/ssl/certs/Baltimore_CyberTrust_Root.pem"
- name: Submit code coverage report to Codecov.io
- uses: codecov/codecov-action@v2
+ uses: codecov/codecov-action@v3
diff --git a/.github/workflows/doctest.yml b/.github/workflows/doctest.yml
index 3478705..47f9916 100644
--- a/.github/workflows/doctest.yml
+++ b/.github/workflows/doctest.yml
@@ -12,9 +12,9 @@ jobs:
- name: Set up Python ${{ matrix.python-version }} environment
uses: actions/setup-python@v2
with:
- python-version: "3.10"
+ python-version: "3.11"
- name: Run pytest with doctest args
run: |
- pip3 install pytest 'websocket-client[optional]' rel
+ pip3 install pytest 'websocket-client[docs]' rel
pytest ./docs/source -v --doctest-glob="*.rst" --doctest-modules
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 12b6856..e5fdfe7 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -12,7 +12,7 @@ jobs:
- name: Set up Python ${{ matrix.python-version }} environment
uses: actions/setup-python@v2
with:
- python-version: "3.10"
+ python-version: "3.11"
- name: Perform mandatory flake8 linting
run: |
diff --git a/ChangeLog b/ChangeLog
index b80d594..409041a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,11 @@
ChangeLog
============
+- 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)
+ - Updated docs to fix old links and updated CI to include Python 3.11
+
- 1.4.1
- Fix stack growth bug when `run_forever` reconnects (#854)
- Add doctest CI for sphinx docs code examples (d150099)
diff --git a/README.md b/README.md
index 66ca0fd..d5c9bc5 100644
--- a/README.md
+++ b/README.md
@@ -73,10 +73,17 @@ Many more examples are found in the
Most real-world WebSockets situations involve longer-lived connections.
The WebSocketApp `run_forever` loop will automatically try to reconnect
to an open WebSocket connection when a network
-connection is lost if it is provided with a dispatcher parameter,
-and provides a variety of event-based connection controls.
+connection is lost if it is provided with:
+
+- a `dispatcher` argument (async dispatcher like rel or pyevent)
+- a non-zero `reconnect` argument (delay between disconnection and attempted reconnection)
+
+`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
-closes the WebSocket. Customizing behavior when the server closes
+closes the WebSocket gracefully (returning
+[a standard websocket close code](https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1)).
+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)
for the dispatcher to provide automatic reconnection.
@@ -107,7 +114,7 @@ if __name__ == "__main__":
on_error=on_error,
on_close=on_close)
- ws.run_forever(dispatcher=rel) # Set dispatcher to automatic reconnection
+ ws.run_forever(dispatcher=rel, reconnect=5) # Set dispatcher to automatic reconnection, 5 second reconnect delay if connection closed unexpectedly
rel.signal(2, rel.abort) # Keyboard Interrupt
rel.dispatch()
```
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 1d49533..a07281f 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -34,7 +34,7 @@ copyright = '2022'
author = 'liris'
# The full version, including alpha/beta/rc tags
-release = '1.4.1'
+release = '1.4.2'
# -- General configuration ---------------------------------------------------
diff --git a/docs/source/examples.rst b/docs/source/examples.rst
index d3d5b99..9b3a905 100644
--- a/docs/source/examples.rst
+++ b/docs/source/examples.rst
@@ -700,7 +700,7 @@ You can use an asynchronous dispatcher such as `rel <https://pypi.org/project/re
>>> addr = "wss://api.gemini.com/v1/marketdata/%s"
>>> for symbol in ["BTCUSD", "ETHUSD", "ETHBTC"]:
... ws = websocket.WebSocketApp(addr % (symbol,), on_message=lambda w, m : print(m))
- ... ws.run_forever(dispatcher=rel) # doctest: +SKIP
+ ... ws.run_forever(dispatcher=rel, reconnect=3) # doctest: +SKIP
>>> rel.signal(2, rel.abort) # Keyboard Interrupt # doctest: +SKIP
>>> rel.dispatch() # doctest: +SKIP
@@ -739,7 +739,7 @@ The examples are found in the README and are copied here for sphinx doctests to
... on_error=on_error,
... on_close=on_close)
- >>> ws.run_forever(dispatcher=rel) # Set dispatcher to automatic reconnection # doctest: +SKIP
+ >>> ws.run_forever(dispatcher=rel, reconnect=5) # Set dispatcher to automatic reconnection, 5 second reconnect delay if connection closed unexpectedly # doctest: +SKIP
>>> rel.signal(2, rel.abort) # Keyboard Interrupt
<Signal Object | Callback:"abort">
>>> rel.dispatch() # doctest: +SKIP
diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst
index 5f3e3f6..c69a1e7 100644
--- a/docs/source/getting_started.rst
+++ b/docs/source/getting_started.rst
@@ -12,8 +12,7 @@ For an easy example, run the following:
The above command will provide you with an interactive terminal to communicate
with the echo.websocket.events server. This server will echo back any message you
-send it. You can test this WebSocket connection in your browser, without this
-library, by visiting the URL https://websocket.org/echo.html.
+send it.
The wsdump.py script has many additional options too, so it's a great way to try
using this library without writing any custom code. The output of
diff --git a/docs/source/threading.rst b/docs/source/threading.rst
index 51a74af..7870e71 100644
--- a/docs/source/threading.rst
+++ b/docs/source/threading.rst
@@ -60,7 +60,7 @@ trigger the ``on_close()`` function. The highlighted rows show the lines added
exclusively in the second example. This threading approach is identical to the
`echoapp_client.py example <https://github.com/websocket-client/websocket-client/blob/master/examples/echoapp_client.py>`_.
However, further testing found that some WebSocket servers, such as
-ws://echo.websocket.org, do not trigger the ``on_close()`` function.
+ws://echo.websocket.events, do not trigger the ``on_close()`` function.
**NOT working on_close() example, without threading**
diff --git a/setup.py b/setup.py
index b596b64..cb14d1c 100644
--- a/setup.py
+++ b/setup.py
@@ -21,7 +21,7 @@ See the License for the specific language governing permissions and
limitations under the License.
"""
-VERSION = "1.4.1"
+VERSION = "1.4.2"
install_requires = []
tests_require = []
@@ -51,6 +51,7 @@ setup(
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
"Operating System :: MacOS :: MacOS X",
"Operating System :: POSIX",
"Operating System :: Microsoft :: Windows",
diff --git a/websocket/__init__.py b/websocket/__init__.py
index 720a842..588a8f2 100644
--- a/websocket/__init__.py
+++ b/websocket/__init__.py
@@ -23,4 +23,4 @@ from ._exceptions import *
from ._logging import *
from ._socket import *
-__version__ = "1.4.1"
+__version__ = "1.4.2"
diff --git a/websocket/_app.py b/websocket/_app.py
index d57781e..c77a3f0 100644
--- a/websocket/_app.py
+++ b/websocket/_app.py
@@ -5,6 +5,7 @@ import threading
import time
import traceback
from ._abnf import ABNF
+from ._url import parse_url
from ._core import WebSocket, getdefaulttimeout
from ._exceptions import *
from . import _logging
@@ -287,12 +288,12 @@ class WebSocketApp:
HTTP proxy host name.
http_proxy_port: int or str
HTTP proxy port. If not set, set to 80.
+ http_no_proxy: list
+ Whitelisted host names that don't use the proxy.
http_proxy_timeout: int or float
HTTP proxy timeout, default is 60 sec as per python-socks.
http_proxy_auth: tuple
HTTP proxy auth information. tuple of username and password. Default is None.
- http_no_proxy: list
- Whitelisted host names that don't use the proxy.
skip_utf8_validation: bool
skip utf8 validation.
host: str
@@ -303,6 +304,10 @@ class WebSocketApp:
customize reading data from socket.
suppress_origin: bool
suppress outputting origin header.
+ proxy_type: str
+ type of proxy from: http, socks4, socks4a, socks5, socks5h
+ reconnect: int
+ delay interval when reconnecting
Returns
-------
@@ -374,7 +379,7 @@ class WebSocketApp:
self._callback(self.on_open)
- _logging.warning("websocket connected")
+ _logging.info("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"))
@@ -405,7 +410,7 @@ class WebSocketApp:
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)
@@ -437,7 +442,7 @@ class WebSocketApp:
teardown()
custom_dispatcher = bool(dispatcher)
- dispatcher = self.create_dispatcher(ping_timeout, dispatcher, not not sslopt)
+ dispatcher = self.create_dispatcher(ping_timeout, dispatcher, parse_url(self.url)[3])
if ping_interval:
event = threading.Event()
diff --git a/websocket/_core.py b/websocket/_core.py
index 73d38b1..1d68829 100644
--- a/websocket/_core.py
+++ b/websocket/_core.py
@@ -46,8 +46,11 @@ class WebSocket:
>>> import websocket
>>> ws = websocket.WebSocket()
- >>> ws.connect("ws://echo.websocket.org")
+ >>> ws.connect("ws://echo.websocket.events")
+ >>> ws.recv()
+ 'echo.websocket.events sponsored by Lob.com'
>>> ws.send("Hello, Server")
+ 19
>>> ws.recv()
'Hello, Server'
>>> ws.close()
@@ -203,7 +206,7 @@ class WebSocket:
If you set "header" list object, you can set your own custom header.
>>> ws = WebSocket()
- >>> ws.connect("ws://echo.websocket.org/",
+ >>> ws.connect("ws://echo.websocket.events",
... header=["User-Agent: MyProgram",
... "x-custom: header"])
@@ -283,7 +286,7 @@ class WebSocket:
"""
Send the data frame.
- >>> ws = create_connection("ws://echo.websocket.org/")
+ >>> ws = create_connection("ws://echo.websocket.events")
>>> frame = ABNF.create_frame("Hello", ABNF.OPCODE_TEXT)
>>> ws.send_frame(frame)
>>> cont_frame = ABNF.create_frame("My name is ", ABNF.OPCODE_CONT, 0)
@@ -543,7 +546,7 @@ def create_connection(url, timeout=None, class_=WebSocket, **options):
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/",
+ >>> conn = create_connection("ws://echo.websocket.events",
... header=["User-Agent: MyProgram",
... "x-custom: header"])
diff --git a/websocket/_handshake.py b/websocket/_handshake.py
index 6a57c95..07a4cfb 100644
--- a/websocket/_handshake.py
+++ b/websocket/_handshake.py
@@ -101,7 +101,6 @@ def _get_handshake_headers(resource, url, host, port, options):
# Append Sec-WebSocket-Key & Sec-WebSocket-Version if not manually specified
if not options.get('header') or 'Sec-WebSocket-Key' not in options['header']:
- key = _create_sec_websocket_key()
headers.append("Sec-WebSocket-Key: %s" % key)
else:
key = options['header']['Sec-WebSocket-Key']
diff --git a/websocket/tests/test_app.py b/websocket/tests/test_app.py
index 8614d08..5526d3e 100644
--- a/websocket/tests/test_app.py
+++ b/websocket/tests/test_app.py
@@ -191,7 +191,7 @@ class WebSocketAppTest(unittest.TestCase):
""" Test WebSocketApp binary opcode
"""
# The lack of wss:// in the URL below is on purpose
- app = ws.WebSocketApp('streaming.vn.teslamotors.com/streaming/')
+ 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")
diff --git a/websocket/tests/test_websocket.py b/websocket/tests/test_websocket.py
index ae42ab5..d47d73e 100644
--- a/websocket/tests/test_websocket.py
+++ b/websocket/tests/test_websocket.py
@@ -432,7 +432,7 @@ class HandshakeTest(unittest.TestCase):
self.assertRaises(ws._exceptions.WebSocketBadStatusException,
websock3.connect, "wss://api.bitfinex.com/ws/2", cookie="chocolate",
origin="testing_websockets.com",
- host="echo.websocket.org/websocket-client-test",
+ host="echo.websocket.events/websocket-client-test",
subprotocols=["testproto"],
connection="Upgrade",
header={"CustomHeader1":"123",