diff --git a/.audit/bblommers_chore-apply-ruff-up.md b/.audit/bblommers_chore-apply-ruff-up.md new file mode 100644 index 000000000..0afbf8eb9 --- /dev/null +++ b/.audit/bblommers_chore-apply-ruff-up.md @@ -0,0 +1,8 @@ +- [x] I did **not** use any AI-assistance tools to help create this pull request. +- [ ] I **did** use AI-assistance tools to *help* create this pull request. +- [x] I have read, understood and followed the projects' [AI Policy](https://github.com/crossbario/autobahn-python/blob/main/AI_POLICY.md) when creating code, documentation etc. for this pull request. + +Submitted by: @bblommers +Date: 2026-01-09 +Related issue(s): #1841 +Branch: bblommers:chore-apply-ruff-up diff --git a/src/autobahn/__main__.py b/src/autobahn/__main__.py index a047afb04..d30ffe594 100644 --- a/src/autobahn/__main__.py +++ b/src/autobahn/__main__.py @@ -231,7 +231,7 @@ def do_call(reactor, session, options): call_kwargs = {k: v for k, v in options.keyword} results = yield session.call(options.uri, *call_args, **call_kwargs) - print("result: {}".format(results)) + print(f"result: {results}") @inlineCallbacks @@ -260,11 +260,11 @@ def do_register(reactor, session, options): @inlineCallbacks def called(*args, **kw): - print("called: args={}, kwargs={}".format(args, kw), file=sys.stderr) + print(f"called: args={args}, kwargs={kw}", file=sys.stderr) env = copy(os.environ) env["WAMP_ARGS"] = " ".join(args) env["WAMP_ARGS_JSON"] = json.dumps(args) - env["WAMP_KWARGS"] = " ".join("{}={}".format(k, v) for k, v in kw.items()) + env["WAMP_KWARGS"] = " ".join(f"{k}={v}" for k, v in kw.items()) env["WAMP_KWARGS_JSON"] = json.dumps(kw) exe = os.path.abspath(options.command[0]) @@ -286,7 +286,7 @@ def processExited(self, reason): code = yield done if code != 0: - print("Failed with exit-code {}".format(code)) + print(f"Failed with exit-code {code}") if countdown[0]: countdown[0] -= 1 if countdown[0] <= 0: @@ -350,12 +350,12 @@ def _real_main(reactor): exe = options.command[0] if not os.path.isabs(exe): print( - "Full path to the executable required. Found: {}".format(exe), + f"Full path to the executable required. Found: {exe}", file=sys.stderr, ) sys.exit(1) if not os.path.exists(exe): - print("Executable not found: {}".format(exe), file=sys.stderr) + print(f"Executable not found: {exe}", file=sys.stderr) sys.exit(1) subcommands = { @@ -372,9 +372,7 @@ def _real_main(reactor): @inlineCallbacks def _(session, details): print( - "connected: authrole={} authmethod={}".format( - details.authrole, details.authmethod - ), + f"connected: authrole={details.authrole} authmethod={details.authmethod}", file=sys.stderr, ) try: @@ -388,10 +386,10 @@ def _(session, details): @component.on_connectfailure def _(comp, fail): - print("connect failure: {}".format(fail)) + print(f"connect failure: {fail}") failures.append(fail) if options.max_failures > 0 and len(failures) > options.max_failures: - print("Too many failures ({}). Exiting".format(len(failures))) + print(f"Too many failures ({len(failures)}). Exiting") reactor.stop() yield component.start(reactor) diff --git a/src/autobahn/_flatc/__init__.py b/src/autobahn/_flatc/__init__.py index a0734f27e..f57e6030d 100644 --- a/src/autobahn/_flatc/__init__.py +++ b/src/autobahn/_flatc/__init__.py @@ -53,7 +53,6 @@ import subprocess import sys from pathlib import Path -from typing import List, Optional def get_flatc_path() -> Path: @@ -79,7 +78,7 @@ def get_flatc_path() -> Path: return flatc_path -def run_flatc(args: List[str], cwd: Optional[str] = None) -> int: +def run_flatc(args: list[str], cwd: str | None = None) -> int: """ Run the bundled flatc with the given arguments. diff --git a/src/autobahn/asyncio/__init__.py b/src/autobahn/asyncio/__init__.py index ee96707cd..c83d75c51 100644 --- a/src/autobahn/asyncio/__init__.py +++ b/src/autobahn/asyncio/__init__.py @@ -52,18 +52,9 @@ if USES_NVX: import cffi - __ident__ = "Autobahn/{}-NVXCFFI/{}-asyncio-{}/{}".format( - autobahn.__version__, - cffi.__version__, - platform.python_implementation(), - platform.python_version(), - ) + __ident__ = f"Autobahn/{autobahn.__version__}-NVXCFFI/{cffi.__version__}-asyncio-{platform.python_implementation()}/{platform.python_version()}" else: - __ident__ = "Autobahn/{}-asyncio-{}/{}".format( - autobahn.__version__, - platform.python_implementation(), - platform.python_version(), - ) + __ident__ = f"Autobahn/{autobahn.__version__}-asyncio-{platform.python_implementation()}/{platform.python_version()}" """ Identification string for the Autobahn|Python asyncio backend. diff --git a/src/autobahn/asyncio/component.py b/src/autobahn/asyncio/component.py index 777540eaa..a903303a5 100644 --- a/src/autobahn/asyncio/component.py +++ b/src/autobahn/asyncio/component.py @@ -89,7 +89,7 @@ def _create_transport_factory(loop, transport, session_factory): factory.setProtocolOptions(**{_camel_case_from_snake_case(k): v}) except (TypeError, KeyError): raise ValueError( - "Unknown {} transport option: {}={}".format(transport.type, k, v) + f"Unknown {transport.type} transport option: {k}={v}" ) return factory @@ -120,7 +120,7 @@ def _check_native_endpoint(self, endpoint): if isinstance(endpoint, dict): if "tls" in endpoint: tls = endpoint["tls"] - if isinstance(tls, (dict, bool)): + if isinstance(tls, dict | bool): pass elif isinstance(tls, ssl.SSLContext): pass @@ -149,9 +149,7 @@ def _connect_transport(self, loop, transport, session_factory, done): timeout = transport.endpoint.get("timeout", 10) # in seconds if type(timeout) != int: raise ValueError( - "invalid type {} for timeout in client endpoint configuration".format( - type(timeout) - ) + f"invalid type {type(timeout)} for timeout in client endpoint configuration" ) # do we support HTTPS proxies? @@ -167,33 +165,25 @@ def _connect_transport(self, loop, transport, session_factory, done): version = transport.endpoint.get("version", 4) if version not in [4, 6]: raise ValueError( - "invalid IP version {} in client endpoint configuration".format( - version - ) + f"invalid IP version {version} in client endpoint configuration" ) host = transport.endpoint["host"] if type(host) != str: raise ValueError( - "invalid type {} for host in client endpoint configuration".format( - type(host) - ) + f"invalid type {type(host)} for host in client endpoint configuration" ) port = transport.endpoint["port"] if type(port) != int: raise ValueError( - "invalid type {} for port in client endpoint configuration".format( - type(port) - ) + f"invalid type {type(port)} for port in client endpoint configuration" ) timeout = transport.endpoint.get("timeout", 10) # in seconds if type(timeout) != int: raise ValueError( - "invalid type {} for timeout in client endpoint configuration".format( - type(timeout) - ) + f"invalid type {type(timeout)} for timeout in client endpoint configuration" ) tls = transport.endpoint.get("tls", None) @@ -205,14 +195,12 @@ def _connect_transport(self, loop, transport, session_factory, done): for k in tls.keys(): if k not in ["hostname", "trust_root"]: raise ValueError( - "Invalid key '{}' in 'tls' config".format(k) + f"Invalid key '{k}' in 'tls' config" ) hostname = tls.get("hostname", host) if type(hostname) != str: raise ValueError( - "invalid type {} for hostname in TLS client endpoint configuration".format( - hostname - ) + f"invalid type {hostname} for hostname in TLS client endpoint configuration" ) cert_fname = tls.get("trust_root", None) @@ -234,9 +222,7 @@ def _connect_transport(self, loop, transport, session_factory, done): else: raise RuntimeError( - 'unknown type {} for "tls" configuration in transport'.format( - type(tls) - ) + f'unknown type {type(tls)} for "tls" configuration in transport' ) f = loop.create_connection( diff --git a/src/autobahn/asyncio/rawsocket.py b/src/autobahn/asyncio/rawsocket.py index f118fb5bf..97eb57ba2 100644 --- a/src/autobahn/asyncio/rawsocket.py +++ b/src/autobahn/asyncio/rawsocket.py @@ -61,11 +61,11 @@ class PrefixProtocol(asyncio.Protocol): max_length = 16 * 1024 * 1024 max_length_send = max_length log = txaio.make_logger() # @UndefinedVariable - peer: Optional[str] = None - is_server: Optional[bool] = None + peer: str | None = None + is_server: bool | None = None @property - def transport_details(self) -> Optional[TransportDetails]: + def transport_details(self) -> TransportDetails | None: """ Implements :func:`autobahn.wamp.interfaces.ITransport.transport_details` """ @@ -221,7 +221,7 @@ def data_received(self, data): try: self.process_handshake() except HandshakeError as e: - self.protocol_error("Handshake error : {err}".format(err=e)) + self.protocol_error(f"Handshake error : {e}") return self._handshake_done = True self._on_handshake_complete() @@ -244,7 +244,7 @@ def data_received(self, data): class HandshakeError(Exception): def __init__(self, msg, code=0): - Exception.__init__(self, msg if not code else msg + " : %s" % ERRMAP.get(code)) + Exception.__init__(self, msg if not code else msg + f" : {ERRMAP.get(code)}") class RawSocketClientProtocol(RawSocketProtocol): @@ -259,9 +259,7 @@ def process_handshake(self): raise HandshakeError("Server returned handshake error", err) if self.serializer_id != ser_id: raise HandshakeError( - "Server returned different serializer {0} then requested {1}".format( - ser_id, self.serializer_id - ) + f"Server returned different serializer {ser_id} then requested {self.serializer_id}" ) @property @@ -293,13 +291,13 @@ def send_response(lexp, ser_id): if not self.supports_serializer(ser_id): send_response(ERR_SERIALIZER_UNSUPPORTED, 0) raise HandshakeError( - "Serializer unsupported : {ser_id}".format(ser_id=ser_id) + f"Serializer unsupported : {ser_id}" ) send_response(self._length_exp, ser_id) # this is transport independent part of WAMP protocol -class WampRawSocketMixinGeneral(object): +class WampRawSocketMixinGeneral: def _on_handshake_complete(self): self.log.debug("WampRawSocketProtocol: Handshake complete") # RawSocket connection established. Now let the user WAMP session factory @@ -364,9 +362,7 @@ def send(self, msg): except Exception as e: # all exceptions raised from above should be serialization errors .. raise SerializationError( - "WampRawSocketProtocol: unable to serialize WAMP application payload ({0})".format( - e - ) + f"WampRawSocketProtocol: unable to serialize WAMP application payload ({e})" ) else: self.sendString(payload) @@ -385,7 +381,7 @@ def isOpen(self): # this is asyncio dependent part of WAMP protocol -class WampRawSocketMixinAsyncio(object): +class WampRawSocketMixinAsyncio: """ Base class for asyncio-based WAMP-over-RawSocket protocols. """ @@ -474,7 +470,7 @@ def serializer_id(self): return self._serializer.RAWSOCKET_SERIALIZER_ID -class WampRawSocketFactory(object): +class WampRawSocketFactory: """ Adapter class for asyncio-based WebSocket client and server factories.def dataReceived(self, data): """ diff --git a/src/autobahn/asyncio/util.py b/src/autobahn/asyncio/util.py index 307e333b9..0fae5a1d3 100644 --- a/src/autobahn/asyncio/util.py +++ b/src/autobahn/asyncio/util.py @@ -41,7 +41,7 @@ def transport_channel_id( - transport, is_server: bool, channel_id_type: Optional[str] = None + transport, is_server: bool, channel_id_type: str | None = None ) -> bytes: """ Application-layer user authentication protocols are vulnerable to generic @@ -63,7 +63,7 @@ def transport_channel_id( # ssl.CHANNEL_BINDING_TYPES if channel_id_type not in ["tls-unique"]: - raise Exception("invalid channel ID type {}".format(channel_id_type)) + raise Exception(f"invalid channel ID type {channel_id_type}") ssl_obj = transport.get_extra_info("ssl_object") if ssl_obj is None: @@ -96,24 +96,24 @@ def peer2str(transport: asyncio.transports.BaseTransport) -> str: peer = transport.get_extra_info("peername") if isinstance(peer, tuple): ip_ver = 4 if len(peer) == 2 else 6 - return "tcp{2}:{0}:{1}".format(peer[0], peer[1], ip_ver) + return f"tcp{ip_ver}:{peer[0]}:{peer[1]}" elif isinstance(peer, str): - return "unix:{0}".format(peer) + return f"unix:{peer}" else: - return "?:{0}".format(peer) + return f"?:{peer}" except: pass try: proc: Popen = transport.get_extra_info("subprocess") # return 'process:{}'.format(transport.pid) - return "process:{}".format(proc.pid) + return f"process:{proc.pid}" except: pass try: pipe = transport.get_extra_info("pipe") - return "pipe:{}".format(pipe) + return f"pipe:{pipe}" except: pass diff --git a/src/autobahn/asyncio/wamp.py b/src/autobahn/asyncio/wamp.py index ada958429..ad7ccfe7b 100644 --- a/src/autobahn/asyncio/wamp.py +++ b/src/autobahn/asyncio/wamp.py @@ -83,7 +83,7 @@ class ApplicationSessionFactory(protocol.ApplicationSessionFactory): @public -class ApplicationRunner(object): +class ApplicationRunner: """ This class is a convenience tool mainly for development and quick hosting of WAMP application components. @@ -179,7 +179,7 @@ def create(): session = make(cfg) except Exception as e: self.log.error( - "ApplicationSession could not be instantiated: {}".format(e) + f"ApplicationSession could not be instantiated: {e}" ) loop = asyncio.get_event_loop() if loop.is_running(): @@ -249,9 +249,8 @@ def accept(response): else: if self.ssl and not isSecure: raise RuntimeError( - 'ssl argument value passed to %s conflicts with the "ws:" ' + f'ssl argument value passed to {self.__class__.__name__} conflicts with the "ws:" ' 'prefix of the url argument. Did you mean to use "wss:"?' - % self.__class__.__name__ ) ssl = self.ssl diff --git a/src/autobahn/asyncio/websocket.py b/src/autobahn/asyncio/websocket.py index 7049a7114..c19e55487 100644 --- a/src/autobahn/asyncio/websocket.py +++ b/src/autobahn/asyncio/websocket.py @@ -66,8 +66,8 @@ class WebSocketAdapterProtocol(asyncio.Protocol): log = txaio.make_logger() - peer: Optional[str] = None - is_server: Optional[bool] = None + peer: str | None = None + is_server: bool | None = None def connection_made(self, transport): # asyncio networking framework entry point, called by asyncio @@ -240,7 +240,7 @@ def startTLS(self): raise Exception("WSS over explicit proxies not implemented") -class WebSocketAdapterFactory(object): +class WebSocketAdapterFactory: """ Adapter class for asyncio-based WebSocket client and server factories. """ diff --git a/src/autobahn/nvx/test/test_nvx_utf8validator.py b/src/autobahn/nvx/test/test_nvx_utf8validator.py index 1c0da0491..8f951d1df 100644 --- a/src/autobahn/nvx/test/test_nvx_utf8validator.py +++ b/src/autobahn/nvx/test/test_nvx_utf8validator.py @@ -1,4 +1,3 @@ -# coding=utf-8 ############################################################################### # @@ -368,7 +367,7 @@ def _test_utf8_incremental(self, validator, withPositions=True): validator.reset() self.assertEqual( - (True, True, 15, 15)[:k], validator.validate("µ@ßöäüàá".encode("utf8"))[:k] + (True, True, 15, 15)[:k], validator.validate("µ@ßöäüàá".encode())[:k] ) validator.reset() diff --git a/src/autobahn/rawsocket/util.py b/src/autobahn/rawsocket/util.py index 06ec5d824..ef81b544e 100644 --- a/src/autobahn/rawsocket/util.py +++ b/src/autobahn/rawsocket/util.py @@ -72,24 +72,24 @@ def create_url(hostname, port=None, isSecure=False): assert type(isSecure) == bool if hostname == "unix": - netloc = "unix:%s" % port + netloc = f"unix:{port}" else: assert port is None or (type(port) == int and port in range(0, 65535)) if port is not None: - netloc = "%s:%d" % (hostname, port) + netloc = f"{hostname}:{port}" else: if isSecure: - netloc = "{}:443".format(hostname) + netloc = f"{hostname}:443" else: - netloc = "{}:80".format(hostname) + netloc = f"{hostname}:80" if isSecure: scheme = "rss" else: scheme = "rs" - return "{}://{}".format(scheme, netloc) + return f"{scheme}://{netloc}" @public @@ -120,9 +120,7 @@ def parse_url(url): if parsed.scheme not in ["rs", "rss"]: raise Exception( - "invalid RawSocket URL: protocol scheme '{}' is not for RawSocket".format( - parsed.scheme - ) + f"invalid RawSocket URL: protocol scheme '{parsed.scheme}' is not for RawSocket" ) if not parsed.hostname or parsed.hostname == "": @@ -130,12 +128,12 @@ def parse_url(url): if parsed.query is not None and parsed.query != "": raise Exception( - "invalid RawSocket URL: non-empty query '{}'".format(parsed.query) + f"invalid RawSocket URL: non-empty query '{parsed.query}'" ) if parsed.fragment is not None and parsed.fragment != "": raise Exception( - "invalid RawSocket URL: non-empty fragment '{}'".format(parsed.fragment) + f"invalid RawSocket URL: non-empty fragment '{parsed.fragment}'" ) if parsed.hostname == "unix": @@ -155,7 +153,7 @@ def parse_url(url): if parsed.path is not None and parsed.path != "": raise Exception( - "invalid RawSocket URL: non-empty path '{}'".format(parsed.path) + f"invalid RawSocket URL: non-empty path '{parsed.path}'" ) if parsed.port is None or parsed.port == "": @@ -167,6 +165,6 @@ def parse_url(url): tcp_port = int(parsed.port) if tcp_port < 1 or tcp_port > 65535: - raise Exception("invalid port {}".format(tcp_port)) + raise Exception(f"invalid port {tcp_port}") return parsed.scheme == "rss", parsed.hostname, tcp_port diff --git a/src/autobahn/test/test_rng.py b/src/autobahn/test/test_rng.py index 9122dce96..31025ef7b 100644 --- a/src/autobahn/test/test_rng.py +++ b/src/autobahn/test/test_rng.py @@ -79,7 +79,7 @@ def test_non_depleting(self): d = rng.read(1000) # noqa # check available entropy - with open("/proc/sys/kernel/random/entropy_avail", "r") as ent: + with open("/proc/sys/kernel/random/entropy_avail") as ent: ea = int(ent.read()) // 100 if ea not in res: res[ea] = 0 @@ -89,7 +89,7 @@ def test_non_depleting(self): print("\nsystem entropy depletion stats:") for k in skeys: - print("{}: {}".format(k, res[k])) + print(f"{k}: {res[k]}") self.assertTrue(skeys[0] > 0) @@ -102,7 +102,7 @@ def test_depleting(self): d = rng.read(1000) # noqa # check available entropy - with open("/proc/sys/kernel/random/entropy_avail", "r") as ent: + with open("/proc/sys/kernel/random/entropy_avail") as ent: ea = int(ent.read()) // 100 if ea not in res: res[ea] = 0 @@ -112,6 +112,6 @@ def test_depleting(self): print("\nsystem entropy depletion stats:") for k in skeys: - print("{}: {}".format(k, res[k])) + print(f"{k}: {res[k]}") self.assertTrue(skeys[0] == 0) diff --git a/src/autobahn/testutil.py b/src/autobahn/testutil.py index 14c3404bf..b5ae493c9 100644 --- a/src/autobahn/testutil.py +++ b/src/autobahn/testutil.py @@ -25,7 +25,7 @@ ############################################################################### -class FakeTransport(object): +class FakeTransport: _written = b"" _open = True @@ -53,14 +53,14 @@ def unregisterProducer(self): def getPeer(self): # for Twisted, this would be an IAddress - class _FakePeer(object): + class _FakePeer: pass return _FakePeer() def getHost(self): # for Twisted, this would be an IAddress - class _FakeHost(object): + class _FakeHost: pass return _FakeHost() diff --git a/src/autobahn/twisted/__init__.py b/src/autobahn/twisted/__init__.py index 1a1e657ce..aa8225a5f 100644 --- a/src/autobahn/twisted/__init__.py +++ b/src/autobahn/twisted/__init__.py @@ -67,20 +67,9 @@ if USES_NVX: import cffi - __ident__ = "Autobahn/{}-NVXCFFI/{}-Twisted/{}-{}/{}".format( - autobahn.__version__, - cffi.__version__, - twisted.__version__, - platform.python_implementation(), - platform.python_version(), - ) + __ident__ = f"Autobahn/{autobahn.__version__}-NVXCFFI/{cffi.__version__}-Twisted/{twisted.__version__}-{platform.python_implementation()}/{platform.python_version()}" else: - __ident__ = "Autobahn/{}-Twisted/{}-{}/{}".format( - autobahn.__version__, - twisted.__version__, - platform.python_implementation(), - platform.python_version(), - ) + __ident__ = f"Autobahn/{autobahn.__version__}-Twisted/{twisted.__version__}-{platform.python_implementation()}/{platform.python_version()}" """ Identification string for the Autobahn|Python Twisted backend. diff --git a/src/autobahn/twisted/component.py b/src/autobahn/twisted/component.py index 4b39d6458..0d3303aae 100644 --- a/src/autobahn/twisted/component.py +++ b/src/autobahn/twisted/component.py @@ -26,7 +26,6 @@ from functools import wraps -from typing import List from twisted.internet.endpoints import TCP4ClientEndpoint, UNIXClientEndpoint from twisted.internet.error import ReactorNotRunning @@ -108,7 +107,7 @@ def _create_transport_factory(reactor, transport, session_factory): factory.setProtocolOptions(**{_camel_case_from_snake_case(k): v}) except (TypeError, KeyError): raise ValueError( - "Unknown {} transport option: {}={}".format(transport.type, k, v) + f"Unknown {transport.type} transport option: {k}={v}" ) return factory @@ -125,33 +124,25 @@ def _create_transport_endpoint(reactor, endpoint_config): version = endpoint_config.get("version", 4) if version not in [4, 6]: raise ValueError( - "invalid IP version {} in client endpoint configuration".format( - version - ) + f"invalid IP version {version} in client endpoint configuration" ) host = endpoint_config["host"] if type(host) != str: raise ValueError( - "invalid type {} for host in client endpoint configuration".format( - type(host) - ) + f"invalid type {type(host)} for host in client endpoint configuration" ) port = endpoint_config["port"] if type(port) != int: raise ValueError( - "invalid type {} for port in client endpoint configuration".format( - type(port) - ) + f"invalid type {type(port)} for port in client endpoint configuration" ) timeout = endpoint_config.get("timeout", 10) # in seconds if type(timeout) != int: raise ValueError( - "invalid type {} for timeout in client endpoint configuration".format( - type(timeout) - ) + f"invalid type {type(timeout)} for timeout in client endpoint configuration" ) tls = endpoint_config.get("tls", None) @@ -172,19 +163,17 @@ def _create_transport_endpoint(reactor, endpoint_config): for k in tls.keys(): if k not in ["hostname", "trust_root"]: raise ValueError( - "Invalid key '{}' in 'tls' config".format(k) + f"Invalid key '{k}' in 'tls' config" ) hostname = tls.get("hostname", host) if type(hostname) != str: raise ValueError( - "invalid type {} for hostname in TLS client endpoint configuration".format( - hostname - ) + f"invalid type {hostname} for hostname in TLS client endpoint configuration" ) trust_root = None cert_fname = tls.get("trust_root", None) if cert_fname is not None: - trust_root = Certificate.loadPEM(open(cert_fname, "r").read()) + trust_root = Certificate.loadPEM(open(cert_fname).read()) context = optionsForClientTLS(hostname, trustRoot=trust_root) elif isinstance(tls, CertificateOptions): @@ -195,9 +184,7 @@ def _create_transport_endpoint(reactor, endpoint_config): else: raise RuntimeError( - 'unknown type {} for "tls" configuration in transport'.format( - type(tls) - ) + f'unknown type {type(tls)} for "tls" configuration in transport' ) if version == 4: @@ -221,9 +208,7 @@ def _create_transport_endpoint(reactor, endpoint_config): endpoint = txtorcon.TorClientEndpoint(host, port) except ImportError: raise RuntimeError( - "{} appears to be a Tor Onion service, but txtorcon is not installed".format( - host, - ) + f"{host} appears to be a Tor Onion service, but txtorcon is not installed" ) elif version == 4: endpoint = TCP4ClientEndpoint(reactor, host, port, timeout=timeout) @@ -284,7 +269,7 @@ def _check_native_endpoint(self, endpoint): elif isinstance(endpoint, dict): if "tls" in endpoint: tls = endpoint["tls"] - if isinstance(tls, (dict, bool)): + if isinstance(tls, dict | bool): pass elif IOpenSSLClientConnectionCreator.providedBy(tls): pass @@ -373,7 +358,7 @@ def start(self, reactor=None): def run( - components: List[Component], log_level: str = "info", stop_at_close: bool = True + components: list[Component], log_level: str = "info", stop_at_close: bool = True ): """ High-level API to run a series of components. diff --git a/src/autobahn/twisted/cryptosign.py b/src/autobahn/twisted/cryptosign.py index cf0869be7..ebb1c383f 100644 --- a/src/autobahn/twisted/cryptosign.py +++ b/src/autobahn/twisted/cryptosign.py @@ -139,7 +139,7 @@ def on_connect(agent): # we are now connected to the locally running ssh-agent # that agent might be the openssh-agent, or eg on Ubuntu 14.04 by # default the gnome-keyring / ssh-askpass-gnome application - blob = _pack(["ssh-ed25519".encode(), self.public_key(binary=True)]) + blob = _pack([b"ssh-ed25519", self.public_key(binary=True)]) # now ask the agent signature_blob = yield agent.signData(blob, challenge) diff --git a/src/autobahn/twisted/rawsocket.py b/src/autobahn/twisted/rawsocket.py index d3c091a22..fff4681d5 100644 --- a/src/autobahn/twisted/rawsocket.py +++ b/src/autobahn/twisted/rawsocket.py @@ -60,8 +60,8 @@ class WampRawSocketProtocol(Int32StringReceiver): log = txaio.make_logger() - peer: Optional[str] = None - is_server: Optional[bool] = None + peer: str | None = None + is_server: bool | None = None def __init__(self): # set the RawSocket maximum message size by default @@ -69,7 +69,7 @@ def __init__(self): self._transport_details = None @property - def transport_details(self) -> Optional[TransportDetails]: + def transport_details(self) -> TransportDetails | None: """ Implements :func:`autobahn.wamp.interfaces.ITransport.transport_details` """ @@ -78,9 +78,7 @@ def transport_details(self) -> Optional[TransportDetails]: def lengthLimitExceeded(self, length): # override hook in Int32StringReceiver base class that is fired when a message is (to be) received # that is larger than what we agreed to handle (by negotiation in the RawSocket opening handshake) - emsg = "RawSocket connection: length of received message exceeded (message was {} bytes, but current maximum is {} bytes)".format( - length, self.MAX_LENGTH - ) + emsg = f"RawSocket connection: length of received message exceeded (message was {length} bytes, but current maximum is {self.MAX_LENGTH} bytes)" raise PayloadExceededError(emsg) def connectionMade(self): @@ -260,16 +258,12 @@ def send(self, msg): except SerializationError as e: # all exceptions raised from above should be serialization errors .. raise SerializationError( - "WampRawSocketProtocol: unable to serialize WAMP application payload ({0})".format( - e - ) + f"WampRawSocketProtocol: unable to serialize WAMP application payload ({e})" ) else: payload_len = len(payload) if 0 < self._max_len_send < payload_len: - emsg = "tried to send RawSocket message with size {} exceeding payload limit of {} octets".format( - payload_len, self._max_len_send - ) + emsg = f"tried to send RawSocket message with size {payload_len} exceeding payload limit of {self._max_len_send} octets" self.log.warn(emsg) raise PayloadExceededError(emsg) else: diff --git a/src/autobahn/twisted/resource.py b/src/autobahn/twisted/resource.py index 27f1821da..d707daac0 100644 --- a/src/autobahn/twisted/resource.py +++ b/src/autobahn/twisted/resource.py @@ -87,7 +87,7 @@ def getChild(self, path, request): @implementer(IResource) -class WebSocketResource(object): +class WebSocketResource: """ A Twisted Web resource for WebSocket. """ diff --git a/src/autobahn/twisted/test/test_tx_endpoint_plugins.py b/src/autobahn/twisted/test/test_tx_endpoint_plugins.py index b33a79be1..8ce1dc011 100644 --- a/src/autobahn/twisted/test/test_tx_endpoint_plugins.py +++ b/src/autobahn/twisted/test/test_tx_endpoint_plugins.py @@ -43,7 +43,7 @@ def test_parse_client_basic(self): from twisted.internet import reactor from twisted.internet.endpoints import clientFromString, quoteStringArgument - ep_string = "autobahn:{0}:url={1}".format( + ep_string = "autobahn:{}:url={}".format( quoteStringArgument("tcp:localhost:9000"), quoteStringArgument("ws://localhost:9000"), ) diff --git a/src/autobahn/twisted/test/test_wamp_runner.py b/src/autobahn/twisted/test/test_wamp_runner.py index 3ca8f6e90..941c47106 100644 --- a/src/autobahn/twisted/test/test_wamp_runner.py +++ b/src/autobahn/twisted/test/test_wamp_runner.py @@ -33,7 +33,7 @@ @implementer(IReactorTime) -class FakeReactor(object): +class FakeReactor: """ This just fakes out enough reactor methods so .run() can work. """ diff --git a/src/autobahn/twisted/testing/__init__.py b/src/autobahn/twisted/testing/__init__.py index a14c4b2fb..e3830cfe4 100644 --- a/src/autobahn/twisted/testing/__init__.py +++ b/src/autobahn/twisted/testing/__init__.py @@ -61,7 +61,7 @@ @implementer(IHostnameResolver) -class _StaticTestResolver(object): +class _StaticTestResolver: def resolveHostName(self, receiver, hostName, portNumber=0): """ Implement IHostnameResolver which always returns 127.0.0.1:31337 @@ -173,7 +173,7 @@ def add_mapping(proto): return real_client_protocol -class _Kalamazoo(object): +class _Kalamazoo: """ Feeling whimsical about class names, see https://en.wikipedia.org/wiki/Handcar diff --git a/src/autobahn/twisted/util.py b/src/autobahn/twisted/util.py index 3bab8ec09..c587d2fe6 100644 --- a/src/autobahn/twisted/util.py +++ b/src/autobahn/twisted/util.py @@ -27,7 +27,7 @@ import hashlib import os import threading -from typing import Any, Dict, Optional, Union +from typing import Any from autobahn.wamp.types import TransportDetails from twisted.internet.address import IPv4Address, UNIXAddress @@ -87,7 +87,7 @@ def sleep(delay, reactor=None): return d -def peer2str(transport: Union[ITransport, IProcessTransport]) -> str: +def peer2str(transport: ITransport | IProcessTransport) -> str: """ Return a *peer descriptor* given a Twisted transport, for example: @@ -101,24 +101,24 @@ def peer2str(transport: Union[ITransport, IProcessTransport]) -> str: # IMPORTANT: we need to _first_ test for IProcessTransport if IProcessTransport.providedBy(transport): # note the PID of the forked process in the peer descriptor - res = "process:{}".format(transport.pid) + res = f"process:{transport.pid}" elif ITransport.providedBy(transport): - addr: Union[IPv4Address, IPv6Address, UNIXAddress, PipeAddress] = ( + addr: IPv4Address | IPv6Address | UNIXAddress | PipeAddress = ( transport.getPeer() ) if isinstance(addr, IPv4Address): - res = "tcp4:{0}:{1}".format(addr.host, addr.port) + res = f"tcp4:{addr.host}:{addr.port}" elif _HAS_IPV6 and isinstance(addr, IPv6Address): - res = "tcp6:{0}:{1}".format(addr.host, addr.port) + res = f"tcp6:{addr.host}:{addr.port}" elif isinstance(addr, UNIXAddress): if addr.name: - res = "unix:{0}".format(addr.name) + res = f"unix:{addr.name}" else: res = "unix" elif isinstance(addr, PipeAddress): # sadly, we don't have a way to get at the PID of the other side of the pipe # res = "pipe" - res = "process:{0}".format(os.getppid()) + res = f"process:{os.getppid()}" else: # gracefully fallback if we can't map the peer's address res = "unknown" @@ -131,22 +131,20 @@ def peer2str(transport: Union[ITransport, IProcessTransport]) -> str: if not _HAS_TLS: def transport_channel_id( - transport: object, is_server: bool, channel_id_type: Optional[str] = None - ) -> Optional[bytes]: + transport: object, is_server: bool, channel_id_type: str | None = None + ) -> bytes | None: if channel_id_type is None: return b"\x00" * 32 else: raise RuntimeError( - 'cannot determine TLS channel ID of type "{}" when TLS is not available on this system'.format( - channel_id_type - ) + f'cannot determine TLS channel ID of type "{channel_id_type}" when TLS is not available on this system' ) else: def transport_channel_id( - transport: object, is_server: bool, channel_id_type: Optional[str] = None - ) -> Optional[bytes]: + transport: object, is_server: bool, channel_id_type: str | None = None + ) -> bytes | None: """ Return TLS channel ID of WAMP transport of the given TLS channel ID type. @@ -170,14 +168,12 @@ def transport_channel_id( if channel_id_type not in ["tls-unique"]: raise RuntimeError( - 'invalid TLS channel ID type "{}" requested'.format(channel_id_type) + f'invalid TLS channel ID type "{channel_id_type}" requested' ) if not isinstance(transport, TLSMemoryBIOProtocol): raise RuntimeError( - 'cannot determine TLS channel ID of type "{}" when TLS is not available on this transport {}'.format( - channel_id_type, type(transport) - ) + f'cannot determine TLS channel ID of type "{channel_id_type}" when TLS is not available on this transport {type(transport)}' ) # get access to the OpenSSL connection underlying the Twisted protocol @@ -213,15 +209,13 @@ def transport_channel_id( return m.digest() else: raise NotImplementedError( - 'should not arrive here (unhandled channel_id_type "{}")'.format( - channel_id_type - ) + f'should not arrive here (unhandled channel_id_type "{channel_id_type}")' ) if not _HAS_TLS: - def extract_peer_certificate(transport: object) -> Optional[Dict[str, Any]]: + def extract_peer_certificate(transport: object) -> dict[str, Any] | None: """ Dummy when no TLS is available. @@ -234,7 +228,7 @@ def extract_peer_certificate(transport: object) -> Optional[Dict[str, Any]]: def extract_peer_certificate( transport: TLSMemoryBIOProtocol, - ) -> Optional[Dict[str, Any]]: + ) -> dict[str, Any] | None: """ Extract TLS x509 client certificate information from a Twisted stream transport, and return a dict with x509 TLS client certificate information (if the client provided a @@ -276,8 +270,8 @@ def maybe_bytes(_value): for i in range(cert.get_extension_count()): ext = cert.get_extension(i) ext_info = { - "name": "{}".format(maybe_bytes(ext.get_short_name())), - "value": "{}".format(maybe_bytes(ext)), + "name": f"{maybe_bytes(ext.get_short_name())}", + "value": f"{maybe_bytes(ext)}", "critical": ext.get_critical() != 0, } result["extensions"].append(ext_info) @@ -290,13 +284,13 @@ def maybe_bytes(_value): for key, value in name.get_components(): key = maybe_bytes(key) value = maybe_bytes(value) - result[entity]["{}".format(key).lower()] = "{}".format(value) + result[entity][f"{key}".lower()] = f"{value}" return result def create_transport_details( - transport: Union[ITransport, IProcessTransport], is_server: bool + transport: ITransport | IProcessTransport, is_server: bool ) -> TransportDetails: """ Create transport details from Twisted transport. diff --git a/src/autobahn/twisted/wamp.py b/src/autobahn/twisted/wamp.py index c253e16de..6b4d3687a 100644 --- a/src/autobahn/twisted/wamp.py +++ b/src/autobahn/twisted/wamp.py @@ -27,7 +27,7 @@ import binascii import inspect import random -from typing import Any, Dict, List, Optional, Union +from typing import Any import txaio @@ -108,7 +108,7 @@ class ApplicationSessionFactory(protocol.ApplicationSessionFactory): @public -class ApplicationRunner(object): +class ApplicationRunner: """ This class is a convenience tool mainly for development and quick hosting of WAMP application components. @@ -122,18 +122,18 @@ class ApplicationRunner(object): def __init__( self, url: str, - realm: Optional[str] = None, - extra: Optional[Dict[str, Any]] = None, - serializers: Optional[List[ISerializer]] = None, - ssl: Optional[CertificateOptions] = None, - proxy: Optional[Dict[str, Any]] = None, - headers: Optional[Dict[str, Any]] = None, - websocket_options: Optional[Dict[str, Any]] = None, - max_retries: Optional[int] = None, - initial_retry_delay: Optional[float] = None, - max_retry_delay: Optional[float] = None, - retry_delay_growth: Optional[float] = None, - retry_delay_jitter: Optional[float] = None, + realm: str | None = None, + extra: dict[str, Any] | None = None, + serializers: list[ISerializer] | None = None, + ssl: CertificateOptions | None = None, + proxy: dict[str, Any] | None = None, + headers: dict[str, Any] | None = None, + websocket_options: dict[str, Any] | None = None, + max_retries: int | None = None, + initial_retry_delay: float | None = None, + max_retry_delay: float | None = None, + retry_delay_growth: float | None = None, + retry_delay_jitter: float | None = None, ): """ @@ -204,9 +204,9 @@ def run( start_reactor: bool = True, auto_reconnect: bool = False, log_level: str = "info", - endpoint: Optional[IStreamClientEndpoint] = None, - reactor: Optional[IReactorCore] = None, - ) -> Union[type(None), Deferred]: + endpoint: IStreamClientEndpoint | None = None, + reactor: IReactorCore | None = None, + ) -> type(None) | Deferred: """ Run the application component. @@ -341,9 +341,8 @@ def accept(response): if self.ssl is not None: if not isSecure: raise RuntimeError( - 'ssl= argument value passed to %s conflicts with the "ws:" ' + f'ssl= argument value passed to {self.__class__.__name__} conflicts with the "ws:" ' 'prefix of the url argument. Did you mean to use "wss:"?' - % self.__class__.__name__ ) context_factory = self.ssl elif isSecure: @@ -472,7 +471,7 @@ def retry(_): # exception so that after the event-loop exits we can re-raise # it to the caller. - class ErrorCollector(object): + class ErrorCollector: exception = None def __call__(self, failure): @@ -555,7 +554,7 @@ def onDisconnect(self): yield self.app._fire_signal("ondisconnect") -class Application(object): +class Application: """ A WAMP application. The application object provides a simple way of creating, debugging and running WAMP application components. @@ -654,7 +653,7 @@ def decorator(func): _uri = uri else: assert self._prefix is not None - _uri = "{0}.{1}".format(self._prefix, func.__name__) + _uri = f"{self._prefix}.{func.__name__}" if inspect.isgeneratorfunction(func): func = inlineCallbacks(func) @@ -692,7 +691,7 @@ def decorator(func): _uri = uri else: assert self._prefix is not None - _uri = "{0}.{1}".format(self._prefix, func.__name__) + _uri = f"{self._prefix}.{func.__name__}" if inspect.isgeneratorfunction(func): func = inlineCallbacks(func) @@ -861,20 +860,20 @@ def on_disconnect(self): # experimental authentication API -class AuthCryptoSign(object): +class AuthCryptoSign: def __init__(self, **kw): # should put in checkconfig or similar for key in kw.keys(): if key not in ["authextra", "authid", "authrole", "privkey"]: raise ValueError( - "Unexpected key '{}' for {}".format(key, self.__class__.__name__) + f"Unexpected key '{key}' for {self.__class__.__name__}" ) for key in ["privkey"]: if key not in kw: - raise ValueError("Must provide '{}' for cryptosign".format(key)) + raise ValueError(f"Must provide '{key}' for cryptosign") for key in kw.get("authextra", dict()): if key not in ["pubkey", "channel_binding", "trustroot", "challenge"]: - raise ValueError("Unexpected key '{}' in 'authextra'".format(key)) + raise ValueError(f"Unexpected key '{key}' in 'authextra'") from autobahn.wamp.cryptosign import CryptosignKey @@ -904,17 +903,17 @@ def on_challenge(self, session, challenge): IAuthenticator.register(AuthCryptoSign) -class AuthWampCra(object): +class AuthWampCra: def __init__(self, **kw): # should put in checkconfig or similar for key in kw.keys(): if key not in ["authextra", "authid", "authrole", "secret"]: raise ValueError( - "Unexpected key '{}' for {}".format(key, self.__class__.__name__) + f"Unexpected key '{key}' for {self.__class__.__name__}" ) for key in ["secret", "authid"]: if key not in kw: - raise ValueError("Must provide '{}' for wampcra".format(key)) + raise ValueError(f"Must provide '{key}' for wampcra") self._args = kw self._secret = kw.pop("secret") diff --git a/src/autobahn/twisted/websocket.py b/src/autobahn/twisted/websocket.py index 2c7f4cae1..125f9f726 100644 --- a/src/autobahn/twisted/websocket.py +++ b/src/autobahn/twisted/websocket.py @@ -81,7 +81,7 @@ ) -def create_client_agent(reactor) -> "_TwistedWebSocketClientAgent": +def create_client_agent(reactor) -> _TwistedWebSocketClientAgent: """ :returns: an instance implementing IWebSocketClientAgent """ @@ -95,9 +95,7 @@ def check_transport_config(transport_config: str) -> None: # XXX move me to "autobahn.websocket.util" if not isinstance(transport_config, str): raise ValueError( - "'transport_config' must be a string, found {}".format( - type(transport_config) - ) + f"'transport_config' must be a string, found {type(transport_config)}" ) # XXX also accept everything Crossbar has in client transport configs? e.g like: # { "type": "websocket", "endpoint": {"type": "tcp", "host": "example.com", ...}} @@ -127,7 +125,7 @@ def check_client_options(options: dict[str, Any]) -> None: ] for actual_k in options.keys(): if actual_k not in valid_keys: - raise ValueError("'options' may not contain '{}'".format(actual_k)) + raise ValueError(f"'options' may not contain '{actual_k}'") def _endpoint_from_config(reactor, factory, transport_config, options): @@ -476,7 +474,7 @@ def startTLS(self): self.transport.startTLS(self.factory.contextFactory) -class WebSocketAdapterFactory(object): +class WebSocketAdapterFactory: """ Adapter class for Twisted-based WebSocket client and server factories. """ @@ -562,7 +560,7 @@ def __init__(self, *args, **kwargs): @implementer(ITransport) -class WrappingWebSocketAdapter(object): +class WrappingWebSocketAdapter: """ An adapter for stream-based transport over WebSocket. @@ -592,18 +590,14 @@ def onConnect(self, requestOrResponse): return p raise ConnectionDeny( ConnectionDeny.NOT_ACCEPTABLE, - "this server only speaks {0} WebSocket subprotocols".format( - self.factory._subprotocols - ), + f"this server only speaks {self.factory._subprotocols} WebSocket subprotocols", ) elif isinstance(requestOrResponse, ConnectionResponse): response = requestOrResponse if response.protocol not in self.factory._subprotocols: self._fail_connection( protocol.WebSocketProtocol.CLOSE_STATUS_CODE_PROTOCOL_ERROR, - "this client only speaks {0} WebSocket subprotocols".format( - self.factory._subprotocols - ), + f"this client only speaks {self.factory._subprotocols} WebSocket subprotocols", ) self._binaryMode = response.protocol != "base64" else: @@ -626,7 +620,7 @@ def onMessage(self, payload: bytes, isBinary: bool) -> None: except Exception as e: self._fail_connection( protocol.WebSocketProtocol.CLOSE_STATUS_CODE_INVALID_PAYLOAD, - "message payload base64 decoding error: {0}".format(e), + f"message payload base64 decoding error: {e}", ) self._proto.dataReceived(payload) diff --git a/src/autobahn/util.py b/src/autobahn/util.py index 94a35fa84..ff175ef9e 100644 --- a/src/autobahn/util.py +++ b/src/autobahn/util.py @@ -39,7 +39,6 @@ from collections import OrderedDict from datetime import datetime, timedelta from pprint import pformat -from typing import Optional import txaio @@ -159,14 +158,12 @@ def xor(d1: bytes, d2: bytes) -> bytes: :returns: XOR of the binary strings (``XOR(d1, d2)``) """ if type(d1) != bytes: - raise Exception("invalid type {} for d1 - must be binary".format(type(d1))) + raise Exception(f"invalid type {type(d1)} for d1 - must be binary") if type(d2) != bytes: - raise Exception("invalid type {} for d2 - must be binary".format(type(d2))) + raise Exception(f"invalid type {type(d2)} for d2 - must be binary") if len(d1) != len(d2): raise Exception( - "cannot XOR binary string of differing length ({} != {})".format( - len(d1), len(d2) - ) + f"cannot XOR binary string of differing length ({len(d1)} != {len(d2)})" ) d1 = array("B", d1) @@ -200,7 +197,7 @@ def utcstr(ts=None): assert ts is None or isinstance(ts, datetime) if ts is None: ts = datetime.utcnow() - return "{0}Z".format(ts.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]) + return "{}Z".format(ts.strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]) @public @@ -214,7 +211,7 @@ def utcnow(): return utcstr() -class IdGenerator(object): +class IdGenerator: """ ID generator for WAMP request IDs. @@ -375,9 +372,9 @@ def newid(length=16): def generate_token( char_groups: int, chars_per_group: int, - chars: Optional[str] = None, - sep: Optional[str] = None, - lower_case: Optional[bool] = False, + chars: str | None = None, + sep: str | None = None, + lower_case: bool | None = False, ) -> str: """ Generate cryptographically strong tokens, which are strings like `M6X5-YO5W-T5IK`. @@ -418,9 +415,7 @@ def generate_token( """ assert type(char_groups) == int assert type(chars_per_group) == int - assert chars is None or type(chars) == str, "chars must be str, was {}".format( - type(chars) - ) + assert chars is None or type(chars) == str, f"chars must be str, was {type(chars)}" chars = chars or DEFAULT_TOKEN_CHARS if lower_case: chars = chars.lower() @@ -524,10 +519,7 @@ def generate_serial_number(): # first call to this function, as a floating point number, based on the # Win32 function QueryPerformanceCounter(). The resolution is typically # better than one microsecond - if sys.version_info >= (3, 8): - _rtime = time.perf_counter - else: - _rtime = time.clock + _rtime = time.perf_counter _ = _rtime() # this starts wallclock else: # On Unix-like platforms, this used the first available from this list: @@ -549,7 +541,7 @@ def rtime(): return _rtime() -class Stopwatch(object): +class Stopwatch: """ Stopwatch based on walltime. @@ -632,7 +624,7 @@ def stop(self): return elapsed -class Tracker(object): +class Tracker: """ A key-based statistics tracker. """ @@ -672,13 +664,13 @@ def diff(self, start_key, end_key, formatted=True): d = self._timings[end_key] - self._timings[start_key] if formatted: if d < 0.00001: # 10us - s = "%d ns" % round(d * 1000000000.0) + s = f"{round(d * 1000000000.0)} ns" elif d < 0.01: # 10ms - s = "%d us" % round(d * 1000000.0) + s = f"{round(d * 1000000.0)} us" elif d < 10: # 10s - s = "%d ms" % round(d * 1000.0) + s = f"{round(d * 1000.0)} ms" else: - s = "%d s" % round(d) + s = f"{round(d)} s" return s.rjust(8) else: return d @@ -700,7 +692,7 @@ def absolute(self, key): """ elapsed = self[key] if elapsed is None: - raise KeyError('No such key "%s".' % elapsed) + raise KeyError(f'No such key "{elapsed}".') return self._dt_offset + timedelta(seconds=elapsed) def __getitem__(self, key): @@ -716,7 +708,7 @@ def __str__(self): return pformat(self._timings) -class EqualityMixin(object): +class EqualityMixin: """ Mixing to add equality comparison operators to a class. @@ -781,7 +773,7 @@ def wildcards2patterns(wildcards): ] -class ObservableMixin(object): +class ObservableMixin: """ Internal utility for enabling event-listeners on particular objects """ @@ -897,7 +889,7 @@ def fire(self, event, *args, **kwargs): return d_res -class _LazyHexFormatter(object): +class _LazyHexFormatter: """ This is used to avoid calling binascii.hexlify() on data given to log.debug() calls unless debug is active (for example). Like:: @@ -934,10 +926,7 @@ def _maybe_tls_reason(instance): """ if _is_tls_error(instance): ssl_error = instance.args[0][0] - return "SSL error: {msg} (in {func})".format( - func=ssl_error[1], - msg=ssl_error[2], - ) + return f"SSL error: {ssl_error[2]} (in {ssl_error[1]})" return "" @@ -952,7 +941,7 @@ def machine_id() -> str: if platform.isLinux(): try: # why this? see: http://0pointer.de/blog/projects/ids.html - with open("/var/lib/dbus/machine-id", "r") as f: + with open("/var/lib/dbus/machine-id") as f: return f.read().strip() except: # Non-dbus using Linux, get a hostname @@ -978,7 +967,7 @@ def machine_id() -> str: def hl(text, bold=False, color="yellow"): if not isinstance(text, str): - text = "{}".format(text) + text = f"{text}" if _HAS_CLICK: return click.style(text, fg=color, bold=bold) else: @@ -987,7 +976,7 @@ def hl(text, bold=False, color="yellow"): def _qn(obj): if inspect.isclass(obj) or inspect.isfunction(obj) or inspect.ismethod(obj): - qn = "{}.{}".format(obj.__module__, obj.__qualname__) + qn = f"{obj.__module__}.{obj.__qualname__}" else: qn = "unknown" return qn @@ -1002,28 +991,28 @@ def hltype(obj): def hlid(oid): - return hl("{}".format(oid), color="blue", bold=True) + return hl(f"{oid}", color="blue", bold=True) def hluserid(oid): if not isinstance(oid, str): - oid = "{}".format(oid) - return hl('"{}"'.format(oid), color="yellow", bold=True) + oid = f"{oid}" + return hl(f'"{oid}"', color="yellow", bold=True) def hlval(val, color="white", bold=True): - return hl("{}".format(val), color=color, bold=bold) + return hl(f"{val}", color=color, bold=bold) def hlcontract(oid): if not isinstance(oid, str): - oid = "{}".format(oid) - return hl("<{}>".format(oid), color="magenta", bold=True) + oid = f"{oid}" + return hl(f"<{oid}>", color="magenta", bold=True) def with_0x(address): if address and not address.startswith("0x"): - return "0x{address}".format(address=address) + return f"0x{address}" return address @@ -1041,7 +1030,7 @@ def write_keyfile(filepath, tags, msg): f.write(msg) for tag, value in tags.items(): if value: - f.write("{}: {}\n".format(tag, value)) + f.write(f"{tag}: {value}\n") def parse_keyfile(key_path: str, private: bool = True) -> OrderedDict: @@ -1050,7 +1039,7 @@ def parse_keyfile(key_path: str, private: bool = True) -> OrderedDict: returns a dict mapping tags -> values. """ if os.path.exists(key_path) and not os.path.isfile(key_path): - raise Exception("Key file '{}' exists, but isn't a file".format(key_path)) + raise Exception(f"Key file '{key_path}' exists, but isn't a file") allowed_tags = [ # common tags @@ -1071,7 +1060,7 @@ def parse_keyfile(key_path: str, private: bool = True) -> OrderedDict: allowed_tags.extend(["private-key-ed25519", "private-key-eth"]) tags = OrderedDict() # type: ignore - with open(key_path, "r") as key_file: + with open(key_path) as key_file: got_blankline = False for line in key_file.readlines(): if line.strip() == "": @@ -1082,11 +1071,11 @@ def parse_keyfile(key_path: str, private: bool = True) -> OrderedDict: value = value.strip() if tag not in allowed_tags: raise Exception( - "Invalid tag '{}' in key file {}".format(tag, key_path) + f"Invalid tag '{tag}' in key file {key_path}" ) if tag in tags: raise Exception( - "Duplicate tag '{}' in key file {}".format(tag, key_path) + f"Duplicate tag '{tag}' in key file {key_path}" ) tags[tag] = value return tags diff --git a/src/autobahn/wamp/auth.py b/src/autobahn/wamp/auth.py index 26a1b7f94..3aa8715c9 100644 --- a/src/autobahn/wamp/auth.py +++ b/src/autobahn/wamp/auth.py @@ -32,7 +32,6 @@ import random import struct import time -from typing import Dict, Optional from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes @@ -93,14 +92,14 @@ def create_authenticator(name, **kwargs): AuthTicket.name: AuthTicket, }[name] except KeyError: - raise ValueError("Unknown authenticator '{}'".format(name)) + raise ValueError(f"Unknown authenticator '{name}'") # this may raise further ValueErrors if the kwargs are wrong authenticator = klass(**kwargs) return authenticator # experimental authentication API -class AuthAnonymous(object): +class AuthAnonymous: name = "anonymous" def __init__(self, **kw): @@ -127,7 +126,7 @@ class AuthAnonymousProxy(AuthAnonymous): IAuthenticator.register(AuthAnonymousProxy) -class AuthTicket(object): +class AuthTicket: name = "ticket" def __init__(self, **kw): @@ -152,7 +151,7 @@ def on_welcome(self, msg, authextra): IAuthenticator.register(AuthTicket) -class AuthCryptoSign(object): +class AuthCryptoSign: name = "cryptosign" def __init__(self, **kw): @@ -160,11 +159,11 @@ def __init__(self, **kw): for key in kw.keys(): if key not in ["authextra", "authid", "authrole", "privkey"]: raise ValueError( - "Unexpected key '{}' for {}".format(key, self.__class__.__name__) + f"Unexpected key '{key}' for {self.__class__.__name__}" ) for key in ["privkey"]: if key not in kw: - raise ValueError("Must provide '{}' for cryptosign".format(key)) + raise ValueError(f"Must provide '{key}' for cryptosign") from autobahn.wamp.cryptosign import CryptosignKey @@ -236,7 +235,7 @@ def _hash_pbkdf2_secret(password, salt, iterations): return pbkdf2(password, salt, iterations, keylen=32) -class AuthScram(object): +class AuthScram: """ Implements "wamp-scram" authentication for components. @@ -272,13 +271,13 @@ def on_challenge(self, session, challenge): for k in required_args: if k not in challenge.extra: raise RuntimeError( - "WAMP-SCRAM challenge option '{}' is " - " required but not specified".format(k) + f"WAMP-SCRAM challenge option '{k}' is " + " required but not specified" ) for k in challenge.extra: if k not in optional_args + required_args: raise RuntimeError( - "WAMP-SCRAM challenge has unknown attribute '{}'".format(k) + f"WAMP-SCRAM challenge has unknown attribute '{k}'" ) channel_binding = challenge.extra.get("channel_binding", "") @@ -293,9 +292,9 @@ def on_challenge(self, session, challenge): self._auth_message = ( "{client_first_bare},{server_first},{client_final_no_proof}".format( - client_first_bare="n={},r={}".format(authid, client_nonce), - server_first="r={},s={},i={}".format(server_nonce, salt, iterations), - client_final_no_proof="c={},r={}".format(channel_binding, server_nonce), + client_first_bare=f"n={authid},r={client_nonce}", + server_first=f"r={server_nonce},s={salt},i={iterations}", + client_final_no_proof=f"c={channel_binding},r={server_nonce}", ) ).encode("ascii") @@ -311,7 +310,7 @@ def on_challenge(self, session, challenge): self._salted_password = _hash_pbkdf2_secret(password, salt, iterations) else: raise RuntimeError( - "WAMP-SCRAM specified unknown KDF '{}'".format(algorithm) + f"WAMP-SCRAM specified unknown KDF '{algorithm}'" ) client_key = hmac.new( @@ -351,7 +350,7 @@ def on_welcome(self, session, authextra): IAuthenticator.register(AuthScram) -class AuthWampCra(object): +class AuthWampCra: name = "wampcra" def __init__(self, **kw): @@ -359,11 +358,11 @@ def __init__(self, **kw): for key in kw.keys(): if key not in ["authextra", "authid", "authrole", "secret"]: raise ValueError( - "Unexpected key '{}' for {}".format(key, self.__class__.__name__) + f"Unexpected key '{key}' for {self.__class__.__name__}" ) for key in ["secret", "authid"]: if key not in kw: - raise ValueError("Must provide '{}' for wampcra".format(key)) + raise ValueError(f"Must provide '{key}' for wampcra") self._args = kw self._secret = kw.pop("secret") @@ -437,7 +436,7 @@ def compute_totp(secret, offset=0): digest = hmac.new(key, msg, hashlib.sha1).digest() o = 15 & (digest[19]) token = (struct.unpack(">I", digest[o : o + 4])[0] & 0x7FFFFFFF) % 1000000 - return "{0:06d}".format(token) + return f"{token:06d}" @public @@ -469,10 +468,10 @@ def check_totp(secret, ticket): @public def qrcode_from_totp(secret, label, issuer): if type(secret) != str: - raise Exception("secret must be of type unicode, not {}".format(type(secret))) + raise Exception(f"secret must be of type unicode, not {type(secret)}") if type(label) != str: - raise Exception("label must be of type unicode, not {}".format(type(label))) + raise Exception(f"label must be of type unicode, not {type(label)}") try: import qrcode @@ -481,7 +480,7 @@ def qrcode_from_totp(secret, label, issuer): raise Exception("qrcode not installed") return qrcode.make( - "otpauth://totp/{}?secret={}&issuer={}".format(label, secret, issuer), + f"otpauth://totp/{label}?secret={secret}&issuer={issuer}", box_size=3, image_factory=qrcode.image.svg.SvgImage, ).to_string() @@ -630,8 +629,8 @@ def compute_wcs(key, challenge): def derive_scram_credential( - email: str, password: str, salt: Optional[bytes] = None -) -> Dict: + email: str, password: str, salt: bytes | None = None +) -> dict: """ Derive WAMP-SCRAM credentials from user email and password. The SCRAM parameters used are the following (these are also contained in the returned credentials): diff --git a/src/autobahn/wamp/component.py b/src/autobahn/wamp/component.py index 5f62def93..3fa3c7abb 100644 --- a/src/autobahn/wamp/component.py +++ b/src/autobahn/wamp/component.py @@ -67,27 +67,27 @@ def _validate_endpoint(endpoint, check_native_endpoint=None): for k in endpoint.keys(): if k not in ["type", "host", "port", "path", "tls", "timeout", "version"]: - raise ValueError("Invalid key '{}' in endpoint configuration".format(k)) + raise ValueError(f"Invalid key '{k}' in endpoint configuration") if endpoint["type"] == "tcp": for k in ["host", "port"]: if k not in endpoint: - raise ValueError("'{}' required in 'tcp' endpoint config".format(k)) + raise ValueError(f"'{k}' required in 'tcp' endpoint config") for k in ["path"]: if k in endpoint: raise ValueError( - "'{}' not valid in 'tcp' endpoint config".format(k) + f"'{k}' not valid in 'tcp' endpoint config" ) elif endpoint["type"] == "unix": for k in ["path"]: if k not in endpoint: raise ValueError( - "'{}' required for 'unix' endpoint config".format(k) + f"'{k}' required for 'unix' endpoint config" ) for k in ["host", "port", "tls"]: if k in endpoint: raise ValueError( - "'{}' not valid in 'unix' endpoint config".format(k) + f"'{k}' not valid in 'unix' endpoint config" ) else: assert False, "should not arrive here" @@ -106,9 +106,7 @@ def _create_transport(index, transport, check_native_endpoint=None): """ if type(transport) != dict: raise ValueError( - "invalid type {} for transport configuration - must be a dict".format( - type(transport) - ) + f"invalid type {type(transport)} for transport configuration - must be a dict" ) valid_transport_keys = [ @@ -128,7 +126,7 @@ def _create_transport(index, transport, check_native_endpoint=None): ] for k in transport.keys(): if k not in valid_transport_keys: - raise ValueError("'{}' is not a valid configuration item".format(k)) + raise ValueError(f"'{k}' is not a valid configuration item") kind = "websocket" if "type" in transport: @@ -144,7 +142,7 @@ def _create_transport(index, transport, check_native_endpoint=None): if proxy is not None: for k in proxy.keys(): if k not in ["host", "port"]: - raise ValueError("Unknown key '{}' in proxy config".format(k)) + raise ValueError(f"Unknown key '{k}' in proxy config") for k in ["host", "port"]: if k not in proxy: raise ValueError("Proxy config requires '{}'".formaT(k)) @@ -153,14 +151,14 @@ def _create_transport(index, transport, check_native_endpoint=None): if "options" in transport: options = transport["options"] if not isinstance(options, dict): - raise ValueError("options must be a dict, not {}".format(type(options))) + raise ValueError(f"options must be a dict, not {type(options)}") headers = transport.get("headers") if kind == "websocket": for key in ["url"]: if key not in transport: - raise ValueError("Transport requires '{}' key".format(key)) + raise ValueError(f"Transport requires '{key}' key") # endpoint not required; we will deduce from URL if it's not provided # XXX not in the branch I rebased; can this go away? (is it redundant??) if "endpoint" not in transport: @@ -182,9 +180,9 @@ def _create_transport(index, transport, check_native_endpoint=None): if "serializer" in transport: raise ValueError("'serializer' is only for rawsocket; use 'serializers'") if "serializers" in transport: - if not isinstance(transport["serializers"], (list, tuple)): + if not isinstance(transport["serializers"], list | tuple): raise ValueError("'serializers' must be a list of strings") - if not all([isinstance(s, (str, str)) for s in transport["serializers"]]): + if not all([isinstance(s, str | str) for s in transport["serializers"]]): raise ValueError("'serializers' must be a list of strings") valid_serializers = SERID_TO_SER.keys() for serial in transport["serializers"]: @@ -229,7 +227,7 @@ def _create_transport(index, transport, check_native_endpoint=None): raise ValueError("'headers' not supported for rawsocket transport") # always a list; len == 1 for rawsocket if "serializer" in transport: - if not isinstance(transport["serializer"], (str, str)): + if not isinstance(transport["serializer"], str | str): raise ValueError("'serializer' must be a string") serializer_config = [transport["serializer"]] else: @@ -262,7 +260,7 @@ def _create_transport(index, transport, check_native_endpoint=None): ) -class _Transport(object): +class _Transport: """ Thin-wrapper for WAMP transports used by a Connection. """ @@ -518,7 +516,7 @@ def __init__( transports = "ws://127.0.0.1:8080/ws" # allows to provide a URL instead of a list of transports - if isinstance(transports, (str, str)): + if isinstance(transports, str | str): url = transports # 'endpoint' will get filled in by parsing the 'url' transport = { @@ -966,16 +964,14 @@ def _run(reactor, components, done_callback=None): if type(components) != list: raise ValueError( - '"components" must be a list of Component objects - encountered {0}'.format( - type(components) - ) + f'"components" must be a list of Component objects - encountered {type(components)}' ) for c in components: if not isinstance(c, Component): raise ValueError( '"components" must be a list of Component objects - encountered' - "item of type {0}".format(type(c)) + f"item of type {type(c)}" ) # validation complete; proceed with startup diff --git a/src/autobahn/wamp/cryptobox.py b/src/autobahn/wamp/cryptobox.py index 98dec965b..337c6efae 100644 --- a/src/autobahn/wamp/cryptobox.py +++ b/src/autobahn/wamp/cryptobox.py @@ -49,7 +49,7 @@ if HAS_CRYPTOBOX: @public - class Key(object): + class Key: """ Holds originator and responder keys for an URI. @@ -115,7 +115,7 @@ def __init__( ) @public - class SymKey(object): + class SymKey: """ Holds a symmetric key for an URI. """ @@ -124,7 +124,7 @@ def __init__(self, raw=None): pass @public - class KeyRing(object): + class KeyRing: """ A keyring holds (cryptobox) public-private key pairs for use with WAMP-cryptobox payload encryption. The keyring can be set on a WAMP session and then transparently will get used @@ -266,9 +266,7 @@ def decode(self, is_originating, uri, encoded_payload): if encoded_payload.enc_serializer != "json": raise Exception( - "received encrypted payload, but don't know how to process serializer '{}'".format( - encoded_payload.enc_serializer - ) + f"received encrypted payload, but don't know how to process serializer '{encoded_payload.enc_serializer}'" ) payload = _json_loads(payload_ser.decode("utf8")) diff --git a/src/autobahn/wamp/cryptosign.py b/src/autobahn/wamp/cryptosign.py index c5e92592a..8373742e3 100644 --- a/src/autobahn/wamp/cryptosign.py +++ b/src/autobahn/wamp/cryptosign.py @@ -28,7 +28,8 @@ import os import struct from binascii import a2b_hex, b2a_hex -from typing import Any, Callable, Dict, Optional, Union +from typing import Any +from collections.abc import Callable import txaio @@ -97,7 +98,7 @@ def _read_ssh_ed25519_pubkey(keydata): :rtype: tuple """ if type(keydata) != str: - raise Exception("invalid type {} for keydata".format(type(keydata))) + raise Exception(f"invalid type {type(keydata)} for keydata") parts = keydata.strip().split() if len(parts) != 3: @@ -105,18 +106,18 @@ def _read_ssh_ed25519_pubkey(keydata): algo, keydata, comment = parts if algo != "ssh-ed25519": - raise Exception("not a Ed25519 SSH public key (but {})".format(algo)) + raise Exception(f"not a Ed25519 SSH public key (but {algo})") blob = binascii.a2b_base64(keydata) try: key = _unpack(blob)[1] except Exception as e: - raise Exception("could not parse key ({})".format(e)) + raise Exception(f"could not parse key ({e})") if len(key) != 32: raise Exception( - "invalid length {} for embedded raw key (must be 32 bytes)".format(len(key)) + f"invalid length {len(key)} for embedded raw key (must be 32 bytes)" ) return key, comment @@ -222,9 +223,7 @@ def _read_ssh_ed25519_privkey(keydata): if nkeys != 1: raise Exception( - "multiple private keys in a key file not supported (found {} keys)".format( - nkeys - ) + f"multiple private keys in a key file not supported (found {nkeys} keys)" ) if mac: @@ -258,9 +257,7 @@ def _read_ssh_ed25519_privkey(keydata): if len(pad) and (len(pad) >= block_size or pad != _makepad(len(pad))): raise Exception( - "invalid OpenSSH private key (padlen={}, actual_pad={}, expected_pad={})".format( - len(pad), pad, _makepad(len(pad)) - ) + f"invalid OpenSSH private key (padlen={len(pad)}, actual_pad={pad}, expected_pad={_makepad(len(pad))})" ) # secret key (64 octets) = 32 octets seed || 32 octets secret key derived of seed @@ -282,9 +279,7 @@ def _read_signify_ed25519_signature(signature_file): sig = binascii.a2b_base64(f.read().splitlines()[1])[10:] if len(sig) != 64: raise Exception( - "bogus Ed25519 signature: raw signature length was {}, but expected 64".format( - len(sig) - ) + f"bogus Ed25519 signature: raw signature length was {len(sig)}, but expected 64" ) return sig @@ -300,9 +295,7 @@ def _read_signify_ed25519_pubkey(pubkey_file): pubkey = binascii.a2b_base64(f.read().splitlines()[1])[10:] if len(pubkey) != 32: raise Exception( - "bogus Ed25519 public key: raw key length was {}, but expected 32".format( - len(pubkey) - ) + f"bogus Ed25519 public key: raw key length was {len(pubkey)}, but expected 32" ) return pubkey @@ -391,8 +384,8 @@ def _verify_signify_ed25519_signature(pubkey_file, signature_file, message): def _format_challenge( challenge: Challenge, - channel_id_raw: Optional[bytes], - channel_id_type: Optional[str], + channel_id_raw: bytes | None, + channel_id_type: str | None, ) -> bytes: """ Format the challenge based on provided parameters @@ -404,9 +397,7 @@ def _format_challenge( """ if not isinstance(challenge, Challenge): raise Exception( - "challenge must be instance of autobahn.wamp.types.Challenge, not {}".format( - type(challenge) - ) + f"challenge must be instance of autobahn.wamp.types.Challenge, not {type(challenge)}" ) if "challenge" not in challenge.extra: @@ -417,16 +408,12 @@ def _format_challenge( if type(challenge_hex) != str: raise Exception( - "invalid type {} for challenge (expected a hex string)".format( - type(challenge_hex) - ) + f"invalid type {type(challenge_hex)} for challenge (expected a hex string)" ) if len(challenge_hex) != 64: raise Exception( - "unexpected challenge (hex) length: was {}, but expected 64".format( - len(challenge_hex) - ) + f"unexpected challenge (hex) length: was {len(challenge_hex)}, but expected 64" ) # the challenge for WAMP-cryptosign is a 32 bytes random value in Hex encoding (that is, a unicode string) @@ -434,9 +421,7 @@ def _format_challenge( if channel_id_type == "tls-unique": assert len(channel_id_raw) == 32, ( - "unexpected TLS transport channel ID length (was {}, but expected 32)".format( - len(channel_id_raw) - ) + f"unexpected TLS transport channel ID length (was {len(channel_id_raw)}, but expected 32)" ) # with TLS channel binding of type "tls-unique", the message to be signed by the client actually @@ -446,7 +431,7 @@ def _format_challenge( # when no channel binding was requested, the message to be signed by the client is the challenge only data = challenge_raw else: - assert False, 'invalid channel_id_type "{}"'.format(channel_id_type) + assert False, f'invalid channel_id_type "{channel_id_type}"' return data @@ -480,7 +465,7 @@ def process(signature_raw): return d2 - class CryptosignKey(object): + class CryptosignKey: """ A cryptosign private key for signing, and hence usable for authentication or a public key usable for verification (but can't be used for signing). @@ -490,15 +475,15 @@ def __init__( self, key, can_sign: bool, - security_module: Optional[ISecurityModule] = None, - key_no: Optional[int] = None, - comment: Optional[str] = None, + security_module: ISecurityModule | None = None, + key_no: int | None = None, + comment: str | None = None, ) -> None: if not ( isinstance(key, signing.VerifyKey) or isinstance(key, signing.SigningKey) ): - raise Exception("invalid type {} for key".format(type(key))) + raise Exception(f"invalid type {type(key)} for key") assert (can_sign and isinstance(key, signing.SigningKey)) or ( not can_sign and isinstance(key, signing.VerifyKey) @@ -510,21 +495,21 @@ def __init__( self._comment = comment @property - def security_module(self) -> Optional["ISecurityModule"]: + def security_module(self) -> "ISecurityModule" | None: """ Implements :meth:`autobahn.wamp.interfaces.IKey.security_module`. """ return self._security_module @property - def key_no(self) -> Optional[int]: + def key_no(self) -> int | None: """ Implements :meth:`autobahn.wamp.interfaces.IKey.key_no`. """ return self._key_no @property - def comment(self) -> Optional[str]: + def comment(self) -> str | None: """ Implements :meth:`autobahn.wamp.interfaces.IKey.comment`. """ @@ -565,8 +550,8 @@ def sign(self, data: bytes) -> bytes: def sign_challenge( self, challenge: Challenge, - channel_id: Optional[bytes] = None, - channel_id_type: Optional[str] = None, + channel_id: bytes | None = None, + channel_id_type: str | None = None, ) -> bytes: """ Implements :meth:`autobahn.wamp.interfaces.ICryptosignKey.sign_challenge`. @@ -574,15 +559,13 @@ def sign_challenge( assert challenge.method in [ "cryptosign", "cryptosign-proxy", - ], 'unexpected cryptosign challenge with method "{}"'.format( - challenge.method - ) + ], f'unexpected cryptosign challenge with method "{challenge.method}"' data = _format_challenge(challenge, channel_id, channel_id_type) return _sign_challenge(data, self.sign) - def public_key(self, binary: bool = False) -> Union[str, bytes]: + def public_key(self, binary: bool = False) -> str | bytes: """ Returns the public key part of a signing key or the (public) verification key. @@ -601,43 +584,43 @@ def public_key(self, binary: bool = False) -> Union[str, bytes]: @classmethod def from_pubkey( - cls, pubkey: bytes, comment: Optional[str] = None + cls, pubkey: bytes, comment: str | None = None ) -> "CryptosignKey": if not (comment is None or type(comment) == str): - raise ValueError("invalid type {} for comment".format(type(comment))) + raise ValueError(f"invalid type {type(comment)} for comment") if type(pubkey) != bytes: raise ValueError( - "invalid key type {} (expected binary)".format(type(pubkey)) + f"invalid key type {type(pubkey)} (expected binary)" ) if len(pubkey) != 32: raise ValueError( - "invalid key length {} (expected 32)".format(len(pubkey)) + f"invalid key length {len(pubkey)} (expected 32)" ) return cls(key=signing.VerifyKey(pubkey), can_sign=False, comment=comment) @classmethod def from_bytes( - cls, key: bytes, comment: Optional[str] = None + cls, key: bytes, comment: str | None = None ) -> "CryptosignKey": if not (comment is None or type(comment) == str): - raise ValueError("invalid type {} for comment".format(type(comment))) + raise ValueError(f"invalid type {type(comment)} for comment") if type(key) != bytes: raise ValueError( - "invalid key type {} (expected binary)".format(type(key)) + f"invalid key type {type(key)} (expected binary)" ) if len(key) != 32: - raise ValueError("invalid key length {} (expected 32)".format(len(key))) + raise ValueError(f"invalid key length {len(key)} (expected 32)") return cls(key=signing.SigningKey(key), can_sign=True, comment=comment) @classmethod def from_file( - cls, filename: str, comment: Optional[str] = None + cls, filename: str, comment: str | None = None ) -> "CryptosignKey": """ Load an Ed25519 (private) signing key (actually, the seed for the key) from a raw file of 32 bytes length. @@ -653,10 +636,10 @@ def from_file( :param comment: Comment for key (optional). """ if not (comment is None or type(comment) == str): - raise Exception("invalid type {} for comment".format(type(comment))) + raise Exception(f"invalid type {type(comment)} for comment") if type(filename) != str: - raise Exception("invalid type {} for filename".format(filename)) + raise Exception(f"invalid type {filename} for filename") with open(filename, "rb") as f: key_data = f.read() @@ -709,7 +692,7 @@ def from_seedphrase(cls, seedphrase: str, index: int = 0) -> "CryptosignKey": # BIP44 path for WAMP # https://github.com/wamp-proto/wamp-proto/issues/401 # https://github.com/satoshilabs/slips/pull/1322 - derivation_path = "m/44'/655'/0'/0/{}".format(index) + derivation_path = f"m/44'/655'/0'/0/{index}" key_raw = mnemonic_to_private_key(seedphrase, derivation_path) assert type(key_raw) == bytes @@ -744,7 +727,7 @@ def from_keyfile(cls, keyfile: str) -> "CryptosignKey": :return: New instance of :class:`CryptosignKey` """ if not os.path.exists(keyfile) or not os.path.isfile(keyfile): - raise RuntimeError('keyfile "{}" is not a file'.format(keyfile)) + raise RuntimeError(f'keyfile "{keyfile}" is not a file') # now load the private or public key file - this returns a dict which should # include (for a private key): @@ -762,9 +745,7 @@ def from_keyfile(cls, keyfile: str) -> "CryptosignKey": pubkey_ed25519_hex = data.get("public-key-ed25519", None) if pubkey_ed25519_hex is None: raise RuntimeError( - 'neither "private-key-ed25519" nor "public-key-ed25519" found in keyfile {}'.format( - keyfile - ) + f'neither "private-key-ed25519" nor "public-key-ed25519" found in keyfile {keyfile}' ) else: return CryptosignKey.from_pubkey( @@ -775,7 +756,7 @@ def from_keyfile(cls, keyfile: str) -> "CryptosignKey": ICryptosignKey.register(CryptosignKey) - class CryptosignAuthextra(object): + class CryptosignAuthextra: """ WAMP-Cryptosign authextra object. """ @@ -797,22 +778,22 @@ class CryptosignAuthextra(object): def __init__( self, - pubkey: Optional[bytes] = None, - challenge: Optional[bytes] = None, - channel_binding: Optional[str] = None, - channel_id: Optional[bytes] = None, + pubkey: bytes | None = None, + challenge: bytes | None = None, + channel_binding: str | None = None, + channel_id: bytes | None = None, # domain address, certificates are verified against owner of the domain - trustroot: Optional[bytes] = None, + trustroot: bytes | None = None, # FIXME: add delegate address # FIXME: add certificates # FIXME: remove reservation - realm: Optional[bytes] = None, - chain_id: Optional[int] = None, - block_no: Optional[int] = None, - delegate: Optional[bytes] = None, - seeder: Optional[bytes] = None, - bandwidth: Optional[int] = None, - signature: Optional[bytes] = None, + realm: bytes | None = None, + chain_id: int | None = None, + block_no: int | None = None, + delegate: bytes | None = None, + seeder: bytes | None = None, + bandwidth: int | None = None, + signature: bytes | None = None, ): if pubkey: assert len(pubkey) == 32 @@ -846,134 +827,134 @@ def __init__( self._signature = signature @property - def pubkey(self) -> Optional[bytes]: + def pubkey(self) -> bytes | None: return self._pubkey @pubkey.setter - def pubkey(self, value: Optional[bytes]): + def pubkey(self, value: bytes | None): assert value is None or len(value) == 20 self._pubkey = value @property - def trustroot(self) -> Optional[bytes]: + def trustroot(self) -> bytes | None: return self._trustroot @trustroot.setter - def trustroot(self, value: Optional[bytes]): + def trustroot(self, value: bytes | None): assert value is None or len(value) == 20 self._trustroot = value @property - def challenge(self) -> Optional[bytes]: + def challenge(self) -> bytes | None: return self._challenge @challenge.setter - def challenge(self, value: Optional[bytes]): + def challenge(self, value: bytes | None): assert value is None or len(value) == 32 self._challenge = value @property - def channel_binding(self) -> Optional[str]: + def channel_binding(self) -> str | None: return self._channel_binding @channel_binding.setter - def channel_binding(self, value: Optional[str]): + def channel_binding(self, value: str | None): assert value is None or value in ["tls-unique"] self._channel_binding = value @property - def channel_id(self) -> Optional[bytes]: + def channel_id(self) -> bytes | None: return self._channel_id @channel_id.setter - def channel_id(self, value: Optional[bytes]): + def channel_id(self, value: bytes | None): assert value is None or len(value) == 32 self._channel_id = value @property - def realm(self) -> Optional[bytes]: + def realm(self) -> bytes | None: return self._realm @realm.setter - def realm(self, value: Optional[bytes]): + def realm(self, value: bytes | None): assert value is None or len(value) == 20 self._realm = value @property - def chain_id(self) -> Optional[int]: + def chain_id(self) -> int | None: return self._chain_id @chain_id.setter - def chain_id(self, value: Optional[int]): + def chain_id(self, value: int | None): assert value is None or value > 0 self._chain_id = value @property - def block_no(self) -> Optional[int]: + def block_no(self) -> int | None: return self._block_no @block_no.setter - def block_no(self, value: Optional[int]): + def block_no(self, value: int | None): assert value is None or value > 0 self._block_no = value @property - def delegate(self) -> Optional[bytes]: + def delegate(self) -> bytes | None: return self._delegate @delegate.setter - def delegate(self, value: Optional[bytes]): + def delegate(self, value: bytes | None): assert value is None or len(value) == 20 self._delegate = value @property - def seeder(self) -> Optional[bytes]: + def seeder(self) -> bytes | None: return self._seeder @seeder.setter - def seeder(self, value: Optional[bytes]): + def seeder(self, value: bytes | None): assert value is None or len(value) == 20 self._seeder = value @property - def bandwidth(self) -> Optional[int]: + def bandwidth(self) -> int | None: return self._bandwidth @bandwidth.setter - def bandwidth(self, value: Optional[int]): + def bandwidth(self, value: int | None): assert value is None or value > 0 self._bandwidth = value @property - def signature(self) -> Optional[bytes]: + def signature(self) -> bytes | None: return self._signature @signature.setter - def signature(self, value: Optional[bytes]): + def signature(self, value: bytes | None): assert value is None or len(value) == 65 self._signature = value @staticmethod - def parse(data: Dict[str, Any]) -> "CryptosignAuthextra": + def parse(data: dict[str, Any]) -> "CryptosignAuthextra": obj = CryptosignAuthextra() pubkey = data.get("pubkey", None) if pubkey is not None: if type(pubkey) != str: - raise ValueError("invalid type {} for pubkey".format(type(pubkey))) + raise ValueError(f"invalid type {type(pubkey)} for pubkey") if len(pubkey) != 32 * 2: - raise ValueError("invalid length {} of pubkey".format(len(pubkey))) + raise ValueError(f"invalid length {len(pubkey)} of pubkey") obj._pubkey = a2b_hex(pubkey) challenge = data.get("challenge", None) if challenge is not None: if type(challenge) != str: raise ValueError( - "invalid type {} for challenge".format(type(challenge)) + f"invalid type {type(challenge)} for challenge" ) if len(challenge) != 32 * 2: raise ValueError( - "invalid length {} of challenge".format(len(challenge)) + f"invalid length {len(challenge)} of challenge" ) obj._challenge = a2b_hex(challenge) @@ -981,13 +962,11 @@ def parse(data: Dict[str, Any]) -> "CryptosignAuthextra": if channel_binding is not None: if type(channel_binding) != str: raise ValueError( - "invalid type {} for channel_binding".format( - type(channel_binding) - ) + f"invalid type {type(channel_binding)} for channel_binding" ) if channel_binding not in ["tls-unique"]: raise ValueError( - 'invalid value "{}" for channel_binding'.format(channel_binding) + f'invalid value "{channel_binding}" for channel_binding' ) obj._channel_binding = channel_binding @@ -995,11 +974,11 @@ def parse(data: Dict[str, Any]) -> "CryptosignAuthextra": if channel_id is not None: if type(channel_id) != str: raise ValueError( - "invalid type {} for channel_id".format(type(channel_id)) + f"invalid type {type(channel_id)} for channel_id" ) if len(channel_id) != 32 * 2: raise ValueError( - "invalid length {} of channel_id".format(len(channel_id)) + f"invalid length {len(channel_id)} of channel_id" ) obj._channel_id = a2b_hex(channel_id) @@ -1007,15 +986,11 @@ def parse(data: Dict[str, Any]) -> "CryptosignAuthextra": if trustroot is not None: if type(trustroot) != str: raise ValueError( - "invalid type {} for trustroot - expected a string".format( - type(trustroot) - ) + f"invalid type {type(trustroot)} for trustroot - expected a string" ) if not _URI_PAT_REALM_NAME_ETH.match(trustroot): raise ValueError( - 'invalid value "{}" for trustroot - expected an Ethereum address'.format( - type(trustroot) - ) + f'invalid value "{type(trustroot)}" for trustroot - expected an Ethereum address' ) obj._trustroot = a2b_hex(trustroot[2:]) @@ -1023,16 +998,14 @@ def parse(data: Dict[str, Any]) -> "CryptosignAuthextra": if reservation is not None: if type(reservation) != dict: raise ValueError( - "invalid type {} for reservation".format(type(reservation)) + f"invalid type {type(reservation)} for reservation" ) chain_id = reservation.get("chain_id", None) if chain_id is not None: if type(chain_id) != int: raise ValueError( - "invalid type {} for reservation.chain_id - expected an integer".format( - type(chain_id) - ) + f"invalid type {type(chain_id)} for reservation.chain_id - expected an integer" ) obj._chain_id = chain_id @@ -1040,9 +1013,7 @@ def parse(data: Dict[str, Any]) -> "CryptosignAuthextra": if block_no is not None: if type(block_no) != int: raise ValueError( - "invalid type {} for reservation.block_no - expected an integer".format( - type(block_no) - ) + f"invalid type {type(block_no)} for reservation.block_no - expected an integer" ) obj._block_no = block_no @@ -1050,15 +1021,11 @@ def parse(data: Dict[str, Any]) -> "CryptosignAuthextra": if realm is not None: if type(realm) != str: raise ValueError( - "invalid type {} for reservation.realm - expected a string".format( - type(realm) - ) + f"invalid type {type(realm)} for reservation.realm - expected a string" ) if not _URI_PAT_REALM_NAME_ETH.match(realm): raise ValueError( - 'invalid value "{}" for reservation.realm - expected an Ethereum address'.format( - type(realm) - ) + f'invalid value "{type(realm)}" for reservation.realm - expected an Ethereum address' ) obj._realm = a2b_hex(realm[2:]) @@ -1066,15 +1033,11 @@ def parse(data: Dict[str, Any]) -> "CryptosignAuthextra": if delegate is not None: if type(delegate) != str: raise ValueError( - "invalid type {} for reservation.delegate - expected a string".format( - type(delegate) - ) + f"invalid type {type(delegate)} for reservation.delegate - expected a string" ) if not _URI_PAT_REALM_NAME_ETH.match(delegate): raise ValueError( - 'invalid value "{}" for reservation.delegate - expected an Ethereum address'.format( - type(delegate) - ) + f'invalid value "{type(delegate)}" for reservation.delegate - expected an Ethereum address' ) obj._delegate = a2b_hex(delegate[2:]) @@ -1082,15 +1045,11 @@ def parse(data: Dict[str, Any]) -> "CryptosignAuthextra": if seeder is not None: if type(seeder) != str: raise ValueError( - "invalid type {} for reservation.seeder - expected a string".format( - type(seeder) - ) + f"invalid type {type(seeder)} for reservation.seeder - expected a string" ) if not _URI_PAT_REALM_NAME_ETH.match(seeder): raise ValueError( - 'invalid value "{}" for reservation.seeder - expected an Ethereum address'.format( - type(seeder) - ) + f'invalid value "{type(seeder)}" for reservation.seeder - expected an Ethereum address' ) obj._seeder = a2b_hex(seeder[2:]) @@ -1098,9 +1057,7 @@ def parse(data: Dict[str, Any]) -> "CryptosignAuthextra": if bandwidth is not None: if type(bandwidth) != int: raise ValueError( - "invalid type {} for reservation.bandwidth - expected an integer".format( - type(bandwidth) - ) + f"invalid type {type(bandwidth)} for reservation.bandwidth - expected an integer" ) obj._bandwidth = bandwidth @@ -1108,17 +1065,17 @@ def parse(data: Dict[str, Any]) -> "CryptosignAuthextra": if signature is not None: if type(signature) != str: raise ValueError( - "invalid type {} for signature".format(type(signature)) + f"invalid type {type(signature)} for signature" ) if len(signature) != 65 * 2: raise ValueError( - "invalid length {} of signature".format(len(signature)) + f"invalid length {len(signature)} of signature" ) obj._signature = a2b_hex(signature) return obj - def marshal(self) -> Dict[str, Any]: + def marshal(self) -> dict[str, Any]: res = {} # FIXME: marshal check-summed eth addresses diff --git a/src/autobahn/wamp/exception.py b/src/autobahn/wamp/exception.py index 9b68b8d37..c8a04770c 100644 --- a/src/autobahn/wamp/exception.py +++ b/src/autobahn/wamp/exception.py @@ -280,7 +280,7 @@ def error_message(self): :returns: The error message. :rtype: str """ - return "{0}: {1}".format( + return "{}: {}".format( self.error, " ".join([str(a) for a in self.args]), ) @@ -291,17 +291,7 @@ def __unicode__(self): self.kwargs["traceback"] = "..." else: tb = "" - return "ApplicationError(error=<{0}>, args={1}, kwargs={2}, enc_algo={3}, callee={4}, callee_authid={5}, callee_authrole={6}, forward_for={7}){8}".format( - self.error, - list(self.args), - self.kwargs, - self.enc_algo, - self.callee, - self.callee_authid, - self.callee_authrole, - self.forward_for, - tb, - ) + return f"ApplicationError(error=<{self.error}>, args={list(self.args)}, kwargs={self.kwargs}, enc_algo={self.enc_algo}, callee={self.callee}, callee_authid={self.callee_authid}, callee_authrole={self.callee_authrole}, forward_for={self.forward_for}){tb}" def __str__(self): return self.__unicode__() diff --git a/src/autobahn/wamp/interfaces.py b/src/autobahn/wamp/interfaces.py index 110b9c669..95de22c2a 100644 --- a/src/autobahn/wamp/interfaces.py +++ b/src/autobahn/wamp/interfaces.py @@ -24,11 +24,12 @@ # ############################################################################### +from __future__ import annotations + import abc -from typing import Any, Callable, Dict, List, Optional, Tuple, Union +from typing import Any +from collections.abc import Callable -# FIXME: see ISecurityModule.__iter__ -# from collections.abc import Iterator from autobahn.util import public from autobahn.wamp.message import Message, Welcome from autobahn.wamp.types import ( @@ -99,7 +100,7 @@ def serialize(self, obj: Any) -> bytes: @public @abc.abstractmethod - def unserialize(self, payload: bytes) -> List[Any]: + def unserialize(self, payload: bytes) -> list[Any]: """ Deserialize objects from a byte string. @@ -118,7 +119,7 @@ class ISerializer(abc.ABC): @public @property @abc.abstractmethod - def MESSAGE_TYPE_MAP(self) -> Dict[int, "IMessage"]: + def MESSAGE_TYPE_MAP(self) -> dict[int, IMessage]: """ Mapping of WAMP message type codes to WAMP message classes. """ @@ -166,7 +167,7 @@ def MIME_TYPE(self) -> str: @public @abc.abstractmethod - def serialize(self, message: "IMessage") -> Tuple[bytes, bool]: + def serialize(self, message: IMessage) -> tuple[bytes, bool]: """ Serializes a WAMP message to bytes for sending over a WAMP transport. @@ -178,8 +179,8 @@ def serialize(self, message: "IMessage") -> Tuple[bytes, bool]: @public @abc.abstractmethod def unserialize( - self, payload: bytes, is_binary: Optional[bool] = None - ) -> List["IMessage"]: + self, payload: bytes, is_binary: bool | None = None + ) -> list[IMessage]: """ Deserialize bytes from a transport and parse into WAMP messages. @@ -212,7 +213,7 @@ def MESSAGE_TYPE(self) -> int: @public @staticmethod @abc.abstractmethod - def parse(wmsg) -> "IMessage": + def parse(wmsg) -> IMessage: """ Factory method that parses a unserialized raw message (as returned byte :func:`autobahn.interfaces.ISerializer.unserialize`) into an instance @@ -277,7 +278,7 @@ def isOpen(self) -> bool: @public @property @abc.abstractmethod - def transport_details(self) -> Optional[TransportDetails]: + def transport_details(self) -> TransportDetails | None: """ Return details about the transport (when the transport is open). """ @@ -358,7 +359,7 @@ def config(self) -> ComponentConfig: @public @property @abc.abstractmethod - def transport(self) -> Optional[ITransport]: + def transport(self) -> ITransport | None: """ When the transport this session is attached to is currently open, this property can be read from. The property should be considered read-only. When the transport @@ -368,7 +369,7 @@ def transport(self) -> Optional[ITransport]: @public @property @abc.abstractmethod - def session_details(self) -> Optional[SessionDetails]: + def session_details(self) -> SessionDetails | None: """ Return details about the session, the same as initially provided to the :meth:`ISession.onJoin` callback on an implementation. @@ -407,13 +408,13 @@ def onConnect(self): def join( self, realm: str, - authmethods: Optional[List[str]] = None, - authid: Optional[str] = None, - authrole: Optional[str] = None, - authextra: Optional[Dict[str, Any]] = None, - resumable: Optional[bool] = None, - resume_session: Optional[int] = None, - resume_token: Optional[str] = None, + authmethods: list[str] | None = None, + authid: str | None = None, + authrole: str | None = None, + authextra: dict[str, Any] | None = None, + resumable: bool | None = None, + resume_session: int | None = None, + resume_token: str | None = None, ): """ Attach the session to the given realm. A session is open as soon as it is attached to a realm. @@ -432,7 +433,7 @@ def onChallenge(self, challenge: Challenge) -> str: @public @abc.abstractmethod - def onWelcome(self, welcome: Welcome) -> Optional[str]: + def onWelcome(self, welcome: Welcome) -> str | None: """ Callback fired after the peer has successfully authenticated. If this returns anything other than None/False, the session is @@ -465,7 +466,7 @@ def onJoin(self, details: SessionDetails): @public @abc.abstractmethod - def leave(self, reason: Optional[str] = None, message: Optional[str] = None): + def leave(self, reason: str | None = None, message: str | None = None): """ Actively close this WAMP session. @@ -517,7 +518,7 @@ def is_attached(self) -> bool: @public @abc.abstractmethod - def set_payload_codec(self, payload_codec: Optional["IPayloadCodec"]): + def set_payload_codec(self, payload_codec: IPayloadCodec | None): """ Set a payload codec on the session. To remove a previously set payload codec, set the codec to ``None``. @@ -530,7 +531,7 @@ def set_payload_codec(self, payload_codec: Optional["IPayloadCodec"]): @public @abc.abstractmethod - def get_payload_codec(self) -> Optional["IPayloadCodec"]: + def get_payload_codec(self) -> IPayloadCodec | None: """ Get the current payload codec (if any) for the session. @@ -541,7 +542,7 @@ def get_payload_codec(self) -> Optional["IPayloadCodec"]: @public @abc.abstractmethod - def define(self, exception: Exception, error: Optional[str] = None): + def define(self, exception: Exception, error: str | None = None): """ Defines an exception for a WAMP error in the context of this WAMP session. @@ -553,7 +554,7 @@ def define(self, exception: Exception, error: Optional[str] = None): @public @abc.abstractmethod - def call(self, procedure: str, *args, **kwargs) -> Union[Any, CallResult]: + def call(self, procedure: str, *args, **kwargs) -> Any | CallResult: """ Call a remote procedure. @@ -588,12 +589,12 @@ def call(self, procedure: str, *args, **kwargs) -> Union[Any, CallResult]: @abc.abstractmethod def register( self, - endpoint: Union[Callable, Any], - procedure: Optional[str] = None, - options: Optional[RegisterOptions] = None, - prefix: Optional[str] = None, - check_types: Optional[bool] = None, - ) -> Union[Registration, List[Registration]]: + endpoint: Callable | Any, + procedure: str | None = None, + options: RegisterOptions | None = None, + prefix: str | None = None, + check_types: bool | None = None, + ) -> Registration | list[Registration]: """ Register a procedure for remote calling. @@ -639,7 +640,7 @@ def register( @public @abc.abstractmethod - def publish(self, topic: str, *args, **kwargs) -> Optional[Publication]: + def publish(self, topic: str, *args, **kwargs) -> Publication | None: """ Publish an event to a topic. @@ -674,11 +675,11 @@ def publish(self, topic: str, *args, **kwargs) -> Optional[Publication]: @abc.abstractmethod def subscribe( self, - handler: Union[Callable, Any], - topic: Optional[str] = None, - options: Optional[SubscribeOptions] = None, - check_types: Optional[bool] = None, - ) -> Union[Subscription, List[Subscription]]: + handler: Callable | Any, + topic: str | None = None, + options: SubscribeOptions | None = None, + check_types: bool | None = None, + ) -> Subscription | list[Subscription]: """ Subscribe to a topic for receiving events. @@ -729,7 +730,7 @@ def on_challenge(self, session: ISession, challenge: Challenge): """ @abc.abstractmethod - def on_welcome(self, authextra: Optional[Dict[str, Any]]) -> Optional[str]: + def on_welcome(self, authextra: dict[str, Any] | None) -> str | None: """ This hook is called when the onWelcome/on_welcome hook is invoked in the protocol, with the 'authextra' dict extracted from the @@ -752,7 +753,7 @@ class IKey(abc.ABC): @property @abc.abstractmethod - def security_module(self) -> Optional["ISecurityModule"]: + def security_module(self) -> ISecurityModule | None: """ When this key is hosted by a security module, return a reference. If the key is freestanding (exists of its own outside any security @@ -763,7 +764,7 @@ def security_module(self) -> Optional["ISecurityModule"]: @property @abc.abstractmethod - def key_no(self) -> Optional[int]: + def key_no(self) -> int | None: """ When this key is hosted by a security module, return an identifier to refer to this key within the security module. @@ -789,7 +790,7 @@ def key_type(self) -> str: """ @abc.abstractmethod - def public_key(self, binary: bool = False) -> Union[str, bytes]: + def public_key(self, binary: bool = False) -> str | bytes: """ Returns the public key part of a signing key or the (public) verification key. @@ -837,8 +838,8 @@ class ICryptosignKey(IKey): def sign_challenge( self, challenge: Challenge, - channel_id: Optional[bytes] = None, - channel_id_type: Optional[str] = None, + channel_id: bytes | None = None, + channel_id_type: str | None = None, ) -> bytes: """ Sign the data from the given WAMP challenge message, and the optional TLS channel ID @@ -862,8 +863,8 @@ def verify_challenge( self, challenge: Challenge, signature: bytes, - channel_id: Optional[bytes] = None, - channel_id_type: Optional[str] = None, + channel_id: bytes | None = None, + channel_id_type: str | None = None, ) -> bool: """ Verify the data from the given WAMP challenge message, and the optional TLS channel ID @@ -890,7 +891,7 @@ class IEthereumKey(IKey): """ @abc.abstractmethod - def address(self, binary: bool = False) -> Union[str, bytes]: + def address(self, binary: bool = False) -> str | bytes: """ Returns the Ethereum (public) address of the key (which is derived from the public key). @@ -901,7 +902,7 @@ def address(self, binary: bool = False) -> Union[str, bytes]: """ @abc.abstractmethod - def sign_typed_data(self, data: Dict[str, Any]) -> bytes: + def sign_typed_data(self, data: dict[str, Any]) -> bytes: """ Sign the given typed data according to `EIP712 `_ and create an Ethereum signature. @@ -913,7 +914,7 @@ def sign_typed_data(self, data: Dict[str, Any]) -> bytes: @abc.abstractmethod def verify_typed_data( - self, data: Dict[str, Any], signature: bytes, signer_address: Union[str, bytes] + self, data: dict[str, Any], signature: bytes, signer_address: str | bytes ) -> bool: """ Verify the given typed data according to `EIP712 `_ @@ -983,7 +984,7 @@ def __contains__(self, key_no: int) -> bool: # """ @abc.abstractmethod - def __getitem__(self, key_no: int) -> Union[ICryptosignKey, IEthereumKey]: + def __getitem__(self, key_no: int) -> ICryptosignKey | IEthereumKey: """ Get a key from the security module given the key number. @@ -994,7 +995,7 @@ def __getitem__(self, key_no: int) -> Union[ICryptosignKey, IEthereumKey]: @abc.abstractmethod def __setitem__( - self, key_no: int, key: Union[ICryptosignKey, IEthereumKey] + self, key_no: int, key: ICryptosignKey | IEthereumKey ) -> None: """ diff --git a/src/autobahn/wamp/message.py b/src/autobahn/wamp/message.py index 254f58488..217ffe076 100644 --- a/src/autobahn/wamp/message.py +++ b/src/autobahn/wamp/message.py @@ -238,7 +238,7 @@ def b2a(data, max_len=40): elif data is None: s = "-" else: - s = "{}".format(data) + s = f"{data}" if len(s) > max_len: return s[:max_len] + ".." else: @@ -327,12 +327,12 @@ def check_or_raise_uri( if allow_none: return else: - raise InvalidUriError("{0}: URI cannot be null".format(message)) + raise InvalidUriError(f"{message}: URI cannot be null") if type(value) != str: if not (value is None and allow_none): raise InvalidUriError( - "{0}: invalid type {1} for URI".format(message, type(value)) + f"{message}: invalid type {type(value)} for URI" ) if strict: @@ -352,15 +352,7 @@ def check_or_raise_uri( if not pat.match(value): raise InvalidUriError( - '{0}: invalid value "{1}" for URI (did not match pattern "{2}" with options strict={3}, allow_empty_components={4}, allow_last_empty={5}, allow_none={6})'.format( - message, - value, - pat.pattern, - strict, - allow_empty_components, - allow_last_empty, - allow_none, - ) + f'{message}: invalid value "{value}" for URI (did not match pattern "{pat.pattern}" with options strict={strict}, allow_empty_components={allow_empty_components}, allow_last_empty={allow_last_empty}, allow_none={allow_none})' ) else: return value @@ -381,11 +373,11 @@ def check_or_raise_realm_name(value, message="WAMP message invalid", allow_eth=T :raises: instance of :class:`autobahn.wamp.exception.InvalidUriError` """ if value is None: - raise InvalidUriError("{0}: realm name cannot be null".format(message)) + raise InvalidUriError(f"{message}: realm name cannot be null") if type(value) != str: raise InvalidUriError( - "{0}: invalid type {1} for realm name".format(message, type(value)) + f"{message}: invalid type {type(value)} for realm name" ) if allow_eth: @@ -393,21 +385,16 @@ def check_or_raise_realm_name(value, message="WAMP message invalid", allow_eth=T return value else: raise InvalidUriError( - '{0}: invalid value "{1}" for realm name (did not match patterns ' - '"{2}" or "{3}")'.format( - message, - value, - _URI_PAT_REALM_NAME.pattern, - _URI_PAT_REALM_NAME_ETH.pattern, - ) + f'{message}: invalid value "{value}" for realm name (did not match patterns ' + f'"{_URI_PAT_REALM_NAME.pattern}" or "{_URI_PAT_REALM_NAME_ETH.pattern}")' ) else: if _URI_PAT_REALM_NAME.match(value): return value else: raise InvalidUriError( - '{0}: invalid value "{1}" for realm name (did not match pattern ' - '"{2}")'.format(message, value, _URI_PAT_REALM_NAME.pattern) + f'{message}: invalid value "{value}" for realm name (did not match pattern ' + f'"{_URI_PAT_REALM_NAME.pattern}")' ) @@ -424,11 +411,11 @@ def check_or_raise_id(value: Any, message: str = "WAMP message invalid") -> int: :raises: instance of :class:`autobahn.wamp.exception.ProtocolError` """ if type(value) != int: - raise ProtocolError("{0}: invalid type {1} for ID".format(message, type(value))) + raise ProtocolError(f"{message}: invalid type {type(value)} for ID") # the value 0 for WAMP IDs is possible in certain WAMP messages, e.g. UNREGISTERED with # router revocation signaling! if value < 0 or value > 9007199254740992: # 2**53 - raise ProtocolError("{0}: invalid value {1} for ID".format(message, value)) + raise ProtocolError(f"{message}: invalid value {value} for ID") return value @@ -448,14 +435,12 @@ def check_or_raise_extra( """ if type(value) != dict: raise ProtocolError( - "{0}: invalid type {1} for WAMP extra".format(message, type(value)) + f"{message}: invalid type {type(value)} for WAMP extra" ) for k in value.keys(): if not isinstance(k, str): raise ProtocolError( - "{0}: invalid type {1} for key in WAMP extra ('{2}')".format( - message, type(k), k - ) + f"{message}: invalid type {type(k)} for key in WAMP extra ('{k}')" ) return value @@ -490,19 +475,17 @@ def _validate_kwargs(kwargs, message="WAMP message invalid"): if kwargs is not None: if type(kwargs) != dict: raise ProtocolError( - "{0}: invalid type {1} for WAMP kwargs".format(message, type(kwargs)) + f"{message}: invalid type {type(kwargs)} for WAMP kwargs" ) for k in kwargs.keys(): if not isinstance(k, str): raise ProtocolError( - "{0}: invalid type {1} for key in WAMP kwargs ('{2}')".format( - message, type(k), k - ) + f"{message}: invalid type {type(k)} for key in WAMP kwargs ('{k}')" ) return kwargs -class Message(object): +class Message: """ WAMP message base class. @@ -698,7 +681,7 @@ def serialize(self, serializer): return self._serialized[serializer] -class MessageWithAppPayload(object): +class MessageWithAppPayload: """ Mixin for WAMP messages carrying application payload (Category 4). @@ -903,7 +886,7 @@ def enc_serializer(self, value): self._enc_serializer = value -class MessageWithForwardFor(object): +class MessageWithForwardFor: """ Mixin for WAMP messages with forward_for (Category 3 & 4). @@ -1348,7 +1331,7 @@ def parse(wmsg): if len(wmsg) != 3: raise ProtocolError( - "invalid message length {0} for HELLO".format(len(wmsg)) + f"invalid message length {len(wmsg)} for HELLO" ) realm = check_or_raise_uri(wmsg[1], "'realm' in HELLO", allow_none=True) @@ -1369,22 +1352,20 @@ def parse(wmsg): for role in details_roles: if role not in ["subscriber", "publisher", "caller", "callee"]: raise ProtocolError( - "invalid role '{0}' in 'roles' in 'details' in HELLO".format(role) + f"invalid role '{role}' in 'roles' in 'details' in HELLO" ) role_cls = ROLE_NAME_TO_CLASS[role] details_role = check_or_raise_extra( details_roles[role], - "role '{0}' in 'roles' in 'details' in HELLO".format(role), + f"role '{role}' in 'roles' in 'details' in HELLO", ) if "features" in details_role: check_or_raise_extra( details_role["features"], - "'features' in role '{0}' in 'roles' in 'details' in HELLO".format( - role - ), + f"'features' in role '{role}' in 'roles' in 'details' in HELLO", ) role_features = role_cls(**details_role["features"]) @@ -1399,17 +1380,13 @@ def parse(wmsg): details_authmethods = details["authmethods"] if type(details_authmethods) != list: raise ProtocolError( - "invalid type {0} for 'authmethods' detail in HELLO".format( - type(details_authmethods) - ) + f"invalid type {type(details_authmethods)} for 'authmethods' detail in HELLO" ) for auth_method in details_authmethods: if type(auth_method) != str: raise ProtocolError( - "invalid type {0} for item in 'authmethods' detail in HELLO".format( - type(auth_method) - ) + f"invalid type {type(auth_method)} for item in 'authmethods' detail in HELLO" ) authmethods = details_authmethods @@ -1419,9 +1396,7 @@ def parse(wmsg): details_authid = details["authid"] if type(details_authid) != str: raise ProtocolError( - "invalid type {0} for 'authid' detail in HELLO".format( - type(details_authid) - ) + f"invalid type {type(details_authid)} for 'authid' detail in HELLO" ) authid = details_authid @@ -1431,9 +1406,7 @@ def parse(wmsg): details_authrole = details["authrole"] if type(details_authrole) != str: raise ProtocolError( - "invalid type {0} for 'authrole' detail in HELLO".format( - type(details_authrole) - ) + f"invalid type {type(details_authrole)} for 'authrole' detail in HELLO" ) authrole = details_authrole @@ -1443,9 +1416,7 @@ def parse(wmsg): details_authextra = details["authextra"] if type(details_authextra) != dict: raise ProtocolError( - "invalid type {0} for 'authextra' detail in HELLO".format( - type(details_authextra) - ) + f"invalid type {type(details_authextra)} for 'authextra' detail in HELLO" ) authextra = details_authextra @@ -1455,9 +1426,7 @@ def parse(wmsg): resumable = details["resumable"] if type(resumable) != bool: raise ProtocolError( - "invalid type {0} for 'resumable' detail in HELLO".format( - type(resumable) - ) + f"invalid type {type(resumable)} for 'resumable' detail in HELLO" ) resume_session = None @@ -1465,9 +1434,7 @@ def parse(wmsg): resume_session = details["resume-session"] if type(resume_session) != int: raise ProtocolError( - "invalid type {0} for 'resume-session' detail in HELLO".format( - type(resume_session) - ) + f"invalid type {type(resume_session)} for 'resume-session' detail in HELLO" ) resume_token = None @@ -1475,9 +1442,7 @@ def parse(wmsg): resume_token = details["resume-token"] if type(resume_token) != str: raise ProtocolError( - "invalid type {0} for 'resume-token' detail in HELLO".format( - type(resume_token) - ) + f"invalid type {type(resume_token)} for 'resume-token' detail in HELLO" ) else: if resume_session: @@ -1959,7 +1924,7 @@ def parse(wmsg): if len(wmsg) != 3: raise ProtocolError( - "invalid message length {0} for WELCOME".format(len(wmsg)) + f"invalid message length {len(wmsg)} for WELCOME" ) session = check_or_raise_id(wmsg[1], "'session' in WELCOME") @@ -1978,9 +1943,7 @@ def parse(wmsg): resumed = details["resumed"] if not type(resumed) == bool: raise ProtocolError( - "invalid type {0} for 'resumed' detail in WELCOME".format( - type(resumed) - ) + f"invalid type {type(resumed)} for 'resumed' detail in WELCOME" ) resumable = None @@ -1988,9 +1951,7 @@ def parse(wmsg): resumable = details["resumable"] if not type(resumable) == bool: raise ProtocolError( - "invalid type {0} for 'resumable' detail in WELCOME".format( - type(resumable) - ) + f"invalid type {type(resumable)} for 'resumable' detail in WELCOME" ) resume_token = None @@ -1998,9 +1959,7 @@ def parse(wmsg): resume_token = details["resume_token"] if not type(resume_token) == str: raise ProtocolError( - "invalid type {0} for 'resume_token' detail in WELCOME".format( - type(resume_token) - ) + f"invalid type {type(resume_token)} for 'resume_token' detail in WELCOME" ) elif resumable: raise ProtocolError( @@ -2024,22 +1983,20 @@ def parse(wmsg): for role in details_roles: if role not in ["broker", "dealer"]: raise ProtocolError( - "invalid role '{0}' in 'roles' in 'details' in WELCOME".format(role) + f"invalid role '{role}' in 'roles' in 'details' in WELCOME" ) role_cls = ROLE_NAME_TO_CLASS[role] details_role = check_or_raise_extra( details_roles[role], - "role '{0}' in 'roles' in 'details' in WELCOME".format(role), + f"role '{role}' in 'roles' in 'details' in WELCOME", ) if "features" in details_role: check_or_raise_extra( details_role["features"], - "'features' in role '{0}' in 'roles' in 'details' in WELCOME".format( - role - ), + f"'features' in role '{role}' in 'roles' in 'details' in WELCOME", ) role_features = role_cls(**details_roles[role]["features"]) @@ -2272,7 +2229,7 @@ def parse(wmsg): if len(wmsg) != 3: raise ProtocolError( - "invalid message length {0} for ABORT".format(len(wmsg)) + f"invalid message length {len(wmsg)} for ABORT" ) details = check_or_raise_extra(wmsg[1], "'details' in ABORT") @@ -2284,9 +2241,7 @@ def parse(wmsg): details_message = details["message"] if type(details_message) != str: raise ProtocolError( - "invalid type {0} for 'message' detail in ABORT".format( - type(details_message) - ) + f"invalid type {type(details_message)} for 'message' detail in ABORT" ) message = details_message @@ -2473,13 +2428,13 @@ def parse(wmsg): if len(wmsg) != 3: raise ProtocolError( - "invalid message length {0} for CHALLENGE".format(len(wmsg)) + f"invalid message length {len(wmsg)} for CHALLENGE" ) method = wmsg[1] if type(method) != str: raise ProtocolError( - "invalid type {0} for 'method' in CHALLENGE".format(type(method)) + f"invalid type {type(method)} for 'method' in CHALLENGE" ) extra = check_or_raise_extra(wmsg[2], "'extra' in CHALLENGE") @@ -2650,15 +2605,13 @@ def parse(wmsg): if len(wmsg) != 3: raise ProtocolError( - "invalid message length {0} for AUTHENTICATE".format(len(wmsg)) + f"invalid message length {len(wmsg)} for AUTHENTICATE" ) signature = wmsg[1] if type(signature) != str: raise ProtocolError( - "invalid type {0} for 'signature' in AUTHENTICATE".format( - type(signature) - ) + f"invalid type {type(signature)} for 'signature' in AUTHENTICATE" ) extra = check_or_raise_extra(wmsg[2], "'extra' in AUTHENTICATE") @@ -2852,7 +2805,7 @@ def parse(wmsg): if len(wmsg) != 3: raise ProtocolError( - "invalid message length {0} for GOODBYE".format(len(wmsg)) + f"invalid message length {len(wmsg)} for GOODBYE" ) details = check_or_raise_extra(wmsg[1], "'details' in GOODBYE") @@ -2865,9 +2818,7 @@ def parse(wmsg): details_message = details["message"] if type(details_message) != str: raise ProtocolError( - "invalid type {0} for 'message' detail in GOODBYE".format( - type(details_message) - ) + f"invalid type {type(details_message)} for 'message' detail in GOODBYE" ) message = details_message @@ -2876,9 +2827,7 @@ def parse(wmsg): resumable = details["resumable"] if type(resumable) != bool: raise ProtocolError( - "invalid type {0} for 'resumable' detail in GOODBYE".format( - type(resumable) - ) + f"invalid type {type(resumable)} for 'resumable' detail in GOODBYE" ) obj = Goodbye(reason=reason, message=message, resumable=resumable) @@ -3243,13 +3192,13 @@ def parse(wmsg): if len(wmsg) not in (5, 6, 7): raise ProtocolError( - "invalid message length {0} for ERROR".format(len(wmsg)) + f"invalid message length {len(wmsg)} for ERROR" ) request_type = wmsg[1] if type(request_type) != int: raise ProtocolError( - "invalid type {0} for 'request_type' in ERROR".format(request_type) + f"invalid type {request_type} for 'request_type' in ERROR" ) if request_type not in [ @@ -3262,7 +3211,7 @@ def parse(wmsg): Invocation.MESSAGE_TYPE, ]: raise ProtocolError( - "invalid value {0} for 'request_type' in ERROR".format(request_type) + f"invalid value {request_type} for 'request_type' in ERROR" ) request = check_or_raise_id(wmsg[2], "'request' in ERROR") @@ -3286,23 +3235,19 @@ def parse(wmsg): enc_algo = details.get("enc_algo", None) if enc_algo and not is_valid_enc_algo(enc_algo): raise ProtocolError( - "invalid value {0} for 'enc_algo' detail in EVENT".format(enc_algo) + f"invalid value {enc_algo} for 'enc_algo' detail in EVENT" ) enc_key = details.get("enc_key", None) if enc_key and type(enc_key) != str: raise ProtocolError( - "invalid type {0} for 'enc_key' detail in EVENT".format( - type(enc_key) - ) + f"invalid type {type(enc_key)} for 'enc_key' detail in EVENT" ) enc_serializer = details.get("enc_serializer", None) if enc_serializer and not is_valid_enc_serializer(enc_serializer): raise ProtocolError( - "invalid value {0} for 'enc_serializer' detail in EVENT".format( - enc_serializer - ) + f"invalid value {enc_serializer} for 'enc_serializer' detail in EVENT" ) else: @@ -3310,23 +3255,21 @@ def parse(wmsg): args = wmsg[5] if args is not None and type(args) != list: raise ProtocolError( - "invalid type {0} for 'args' in ERROR".format(type(args)) + f"invalid type {type(args)} for 'args' in ERROR" ) if len(wmsg) > 6: kwargs = wmsg[6] if type(kwargs) != dict: raise ProtocolError( - "invalid type {0} for 'kwargs' in ERROR".format(type(kwargs)) + f"invalid type {type(kwargs)} for 'kwargs' in ERROR" ) if "callee" in details: detail_callee = details["callee"] if type(detail_callee) != int: raise ProtocolError( - "invalid type {0} for 'callee' detail in ERROR".format( - type(detail_callee) - ) + f"invalid type {type(detail_callee)} for 'callee' detail in ERROR" ) callee = detail_callee @@ -3335,9 +3278,7 @@ def parse(wmsg): detail_callee_authid = details["callee_authid"] if type(detail_callee_authid) != str: raise ProtocolError( - "invalid type {0} for 'callee_authid' detail in ERROR".format( - type(detail_callee_authid) - ) + f"invalid type {type(detail_callee_authid)} for 'callee_authid' detail in ERROR" ) callee_authid = detail_callee_authid @@ -3346,9 +3287,7 @@ def parse(wmsg): detail_callee_authrole = details["callee_authrole"] if type(detail_callee_authrole) != str: raise ProtocolError( - "invalid type {0} for 'callee_authrole' detail in ERROR".format( - type(detail_callee_authrole) - ) + f"invalid type {type(detail_callee_authrole)} for 'callee_authrole' detail in ERROR" ) callee_authrole = detail_callee_authrole @@ -4153,7 +4092,7 @@ def parse(wmsg): if len(wmsg) not in (4, 5, 6): raise ProtocolError( - "invalid message length {0} for PUBLISH".format(len(wmsg)) + f"invalid message length {len(wmsg)} for PUBLISH" ) request = check_or_raise_id(wmsg[1], "'request' in PUBLISH") @@ -4170,25 +4109,19 @@ def parse(wmsg): enc_algo = options.get("enc_algo", None) if enc_algo and not is_valid_enc_algo(enc_algo): raise ProtocolError( - "invalid value {0} for 'enc_algo' option in PUBLISH".format( - enc_algo - ) + f"invalid value {enc_algo} for 'enc_algo' option in PUBLISH" ) enc_key = options.get("enc_key", None) if enc_key and type(enc_key) != str: raise ProtocolError( - "invalid type {0} for 'enc_key' option in PUBLISH".format( - type(enc_key) - ) + f"invalid type {type(enc_key)} for 'enc_key' option in PUBLISH" ) enc_serializer = options.get("enc_serializer", None) if enc_serializer and not is_valid_enc_serializer(enc_serializer): raise ProtocolError( - "invalid value {0} for 'enc_serializer' option in PUBLISH".format( - enc_serializer - ) + f"invalid value {enc_serializer} for 'enc_serializer' option in PUBLISH" ) else: @@ -4196,14 +4129,14 @@ def parse(wmsg): args = wmsg[4] if type(args) not in [list, str, bytes]: raise ProtocolError( - "invalid type {0} for 'args' in PUBLISH".format(type(args)) + f"invalid type {type(args)} for 'args' in PUBLISH" ) if len(wmsg) > 5: kwargs = wmsg[5] if type(kwargs) not in [dict, str, bytes]: raise ProtocolError( - "invalid type {0} for 'kwargs' in PUBLISH".format(type(kwargs)) + f"invalid type {type(kwargs)} for 'kwargs' in PUBLISH" ) enc_algo = None @@ -4226,9 +4159,7 @@ def parse(wmsg): option_acknowledge = options["acknowledge"] if type(option_acknowledge) != bool: raise ProtocolError( - "invalid type {0} for 'acknowledge' option in PUBLISH".format( - type(option_acknowledge) - ) + f"invalid type {type(option_acknowledge)} for 'acknowledge' option in PUBLISH" ) acknowledge = option_acknowledge @@ -4237,9 +4168,7 @@ def parse(wmsg): option_exclude_me = options["exclude_me"] if type(option_exclude_me) != bool: raise ProtocolError( - "invalid type {0} for 'exclude_me' option in PUBLISH".format( - type(option_exclude_me) - ) + f"invalid type {type(option_exclude_me)} for 'exclude_me' option in PUBLISH" ) exclude_me = option_exclude_me @@ -4248,17 +4177,13 @@ def parse(wmsg): option_exclude = options["exclude"] if type(option_exclude) != list: raise ProtocolError( - "invalid type {0} for 'exclude' option in PUBLISH".format( - type(option_exclude) - ) + f"invalid type {type(option_exclude)} for 'exclude' option in PUBLISH" ) for _sessionid in option_exclude: if type(_sessionid) != int: raise ProtocolError( - "invalid type {0} for value in 'exclude' option in PUBLISH".format( - type(_sessionid) - ) + f"invalid type {type(_sessionid)} for value in 'exclude' option in PUBLISH" ) exclude = option_exclude @@ -4267,17 +4192,13 @@ def parse(wmsg): option_exclude_authid = options["exclude_authid"] if type(option_exclude_authid) != list: raise ProtocolError( - "invalid type {0} for 'exclude_authid' option in PUBLISH".format( - type(option_exclude_authid) - ) + f"invalid type {type(option_exclude_authid)} for 'exclude_authid' option in PUBLISH" ) for _authid in option_exclude_authid: if type(_authid) != str: raise ProtocolError( - "invalid type {0} for value in 'exclude_authid' option in PUBLISH".format( - type(_authid) - ) + f"invalid type {type(_authid)} for value in 'exclude_authid' option in PUBLISH" ) exclude_authid = option_exclude_authid @@ -4286,17 +4207,13 @@ def parse(wmsg): option_exclude_authrole = options["exclude_authrole"] if type(option_exclude_authrole) != list: raise ProtocolError( - "invalid type {0} for 'exclude_authrole' option in PUBLISH".format( - type(option_exclude_authrole) - ) + f"invalid type {type(option_exclude_authrole)} for 'exclude_authrole' option in PUBLISH" ) for _authrole in option_exclude_authrole: if type(_authrole) != str: raise ProtocolError( - "invalid type {0} for value in 'exclude_authrole' option in PUBLISH".format( - type(_authrole) - ) + f"invalid type {type(_authrole)} for value in 'exclude_authrole' option in PUBLISH" ) exclude_authrole = option_exclude_authrole @@ -4305,17 +4222,13 @@ def parse(wmsg): option_eligible = options["eligible"] if type(option_eligible) != list: raise ProtocolError( - "invalid type {0} for 'eligible' option in PUBLISH".format( - type(option_eligible) - ) + f"invalid type {type(option_eligible)} for 'eligible' option in PUBLISH" ) for sessionId in option_eligible: if type(sessionId) != int: raise ProtocolError( - "invalid type {0} for value in 'eligible' option in PUBLISH".format( - type(sessionId) - ) + f"invalid type {type(sessionId)} for value in 'eligible' option in PUBLISH" ) eligible = option_eligible @@ -4324,17 +4237,13 @@ def parse(wmsg): option_eligible_authid = options["eligible_authid"] if type(option_eligible_authid) != list: raise ProtocolError( - "invalid type {0} for 'eligible_authid' option in PUBLISH".format( - type(option_eligible_authid) - ) + f"invalid type {type(option_eligible_authid)} for 'eligible_authid' option in PUBLISH" ) for _authid in option_eligible_authid: if type(_authid) != str: raise ProtocolError( - "invalid type {0} for value in 'eligible_authid' option in PUBLISH".format( - type(_authid) - ) + f"invalid type {type(_authid)} for value in 'eligible_authid' option in PUBLISH" ) eligible_authid = option_eligible_authid @@ -4343,17 +4252,13 @@ def parse(wmsg): option_eligible_authrole = options["eligible_authrole"] if type(option_eligible_authrole) != list: raise ProtocolError( - "invalid type {0} for 'eligible_authrole' option in PUBLISH".format( - type(option_eligible_authrole) - ) + f"invalid type {type(option_eligible_authrole)} for 'eligible_authrole' option in PUBLISH" ) for _authrole in option_eligible_authrole: if type(_authrole) != str: raise ProtocolError( - "invalid type {0} for value in 'eligible_authrole' option in PUBLISH".format( - type(_authrole) - ) + f"invalid type {type(_authrole)} for value in 'eligible_authrole' option in PUBLISH" ) eligible_authrole = option_eligible_authrole @@ -4362,18 +4267,14 @@ def parse(wmsg): retain = options["retain"] if type(retain) != bool: raise ProtocolError( - "invalid type {0} for 'retain' option in PUBLISH".format( - type(retain) - ) + f"invalid type {type(retain)} for 'retain' option in PUBLISH" ) if "transaction_hash" in options: transaction_hash = options["transaction_hash"] if type(transaction_hash) != str: raise ProtocolError( - "invalid type {0} for 'transaction_hash' option in PUBLISH".format( - type(transaction_hash) - ) + f"invalid type {type(transaction_hash)} for 'transaction_hash' option in PUBLISH" ) if "forward_for" in options: @@ -4563,7 +4464,7 @@ def parse(wmsg): if len(wmsg) != 3: raise ProtocolError( - "invalid message length {0} for PUBLISHED".format(len(wmsg)) + f"invalid message length {len(wmsg)} for PUBLISHED" ) request = check_or_raise_id(wmsg[1], "'request' in PUBLISHED") @@ -4784,7 +4685,7 @@ def parse(wmsg): if len(wmsg) != 4: raise ProtocolError( - "invalid message length {0} for SUBSCRIBE".format(len(wmsg)) + f"invalid message length {len(wmsg)} for SUBSCRIBE" ) request = check_or_raise_id(wmsg[1], "'request' in SUBSCRIBE") @@ -4801,9 +4702,7 @@ def parse(wmsg): option_match = options["match"] if type(option_match) != str: raise ProtocolError( - "invalid type {0} for 'match' option in SUBSCRIBE".format( - type(option_match) - ) + f"invalid type {type(option_match)} for 'match' option in SUBSCRIBE" ) if option_match not in [ @@ -4812,9 +4711,7 @@ def parse(wmsg): Subscribe.MATCH_WILDCARD, ]: raise ProtocolError( - "invalid value {0} for 'match' option in SUBSCRIBE".format( - option_match - ) + f"invalid value {option_match} for 'match' option in SUBSCRIBE" ) match = option_match @@ -4824,9 +4721,7 @@ def parse(wmsg): if type(get_retained) != bool: raise ProtocolError( - "invalid type {0} for 'get_retained' option in SUBSCRIBE".format( - type(get_retained) - ) + f"invalid type {type(get_retained)} for 'get_retained' option in SUBSCRIBE" ) if "forward_for" in options: @@ -4994,7 +4889,7 @@ def parse(wmsg): if len(wmsg) != 3: raise ProtocolError( - "invalid message length {0} for SUBSCRIBED".format(len(wmsg)) + f"invalid message length {len(wmsg)} for SUBSCRIBED" ) request = check_or_raise_id(wmsg[1], "'request' in SUBSCRIBED") @@ -5156,7 +5051,7 @@ def parse(wmsg): if len(wmsg) not in [3, 4]: raise ProtocolError( - "invalid message length {0} for WAMP UNSUBSCRIBE".format(len(wmsg)) + f"invalid message length {len(wmsg)} for WAMP UNSUBSCRIBE" ) request = check_or_raise_id(wmsg[1], "'request' in UNSUBSCRIBE") @@ -5353,7 +5248,7 @@ def parse(wmsg): if len(wmsg) not in [2, 3]: raise ProtocolError( - "invalid message length {0} for UNSUBSCRIBED".format(len(wmsg)) + f"invalid message length {len(wmsg)} for UNSUBSCRIBED" ) request = check_or_raise_id(wmsg[1], "'request' in UNSUBSCRIBED") @@ -5368,9 +5263,7 @@ def parse(wmsg): details_subscription = details["subscription"] if type(details_subscription) != int: raise ProtocolError( - "invalid type {0} for 'subscription' detail in UNSUBSCRIBED".format( - type(details_subscription) - ) + f"invalid type {type(details_subscription)} for 'subscription' detail in UNSUBSCRIBED" ) subscription = details_subscription @@ -5921,7 +5814,7 @@ def parse(wmsg): if len(wmsg) not in (4, 5, 6): raise ProtocolError( - "invalid message length {0} for EVENT".format(len(wmsg)) + f"invalid message length {len(wmsg)} for EVENT" ) subscription = check_or_raise_id(wmsg[1], "'subscription' in EVENT") @@ -5941,23 +5834,19 @@ def parse(wmsg): enc_algo = details.get("enc_algo", None) if enc_algo and not is_valid_enc_algo(enc_algo): raise ProtocolError( - "invalid value {0} for 'enc_algo' detail in EVENT".format(enc_algo) + f"invalid value {enc_algo} for 'enc_algo' detail in EVENT" ) enc_key = details.get("enc_key", None) if enc_key and type(enc_key) != str: raise ProtocolError( - "invalid type {0} for 'enc_key' detail in EVENT".format( - type(enc_key) - ) + f"invalid type {type(enc_key)} for 'enc_key' detail in EVENT" ) enc_serializer = details.get("enc_serializer", None) if enc_serializer and not is_valid_enc_serializer(enc_serializer): raise ProtocolError( - "invalid value {0} for 'enc_serializer' detail in EVENT".format( - enc_serializer - ) + f"invalid value {enc_serializer} for 'enc_serializer' detail in EVENT" ) else: @@ -5965,13 +5854,13 @@ def parse(wmsg): args = wmsg[4] if args is not None and type(args) != list: raise ProtocolError( - "invalid type {0} for 'args' in EVENT".format(type(args)) + f"invalid type {type(args)} for 'args' in EVENT" ) if len(wmsg) > 5: kwargs = wmsg[5] if type(kwargs) != dict: raise ProtocolError( - "invalid type {0} for 'kwargs' in EVENT".format(type(kwargs)) + f"invalid type {type(kwargs)} for 'kwargs' in EVENT" ) publisher = None @@ -5987,9 +5876,7 @@ def parse(wmsg): detail_publisher = details["publisher"] if type(detail_publisher) != int: raise ProtocolError( - "invalid type {0} for 'publisher' detail in EVENT".format( - type(detail_publisher) - ) + f"invalid type {type(detail_publisher)} for 'publisher' detail in EVENT" ) publisher = detail_publisher @@ -5998,9 +5885,7 @@ def parse(wmsg): detail_publisher_authid = details["publisher_authid"] if type(detail_publisher_authid) != str: raise ProtocolError( - "invalid type {0} for 'publisher_authid' detail in EVENT".format( - type(detail_publisher_authid) - ) + f"invalid type {type(detail_publisher_authid)} for 'publisher_authid' detail in EVENT" ) publisher_authid = detail_publisher_authid @@ -6009,9 +5894,7 @@ def parse(wmsg): detail_publisher_authrole = details["publisher_authrole"] if type(detail_publisher_authrole) != str: raise ProtocolError( - "invalid type {0} for 'publisher_authrole' detail in EVENT".format( - type(detail_publisher_authrole) - ) + f"invalid type {type(detail_publisher_authrole)} for 'publisher_authrole' detail in EVENT" ) publisher_authrole = detail_publisher_authrole @@ -6020,9 +5903,7 @@ def parse(wmsg): detail_topic = details["topic"] if type(detail_topic) != str: raise ProtocolError( - "invalid type {0} for 'topic' detail in EVENT".format( - type(detail_topic) - ) + f"invalid type {type(detail_topic)} for 'topic' detail in EVENT" ) topic = detail_topic @@ -6031,18 +5912,14 @@ def parse(wmsg): retained = details["retained"] if type(retained) != bool: raise ProtocolError( - "invalid type {0} for 'retained' detail in EVENT".format( - type(retained) - ) + f"invalid type {type(retained)} for 'retained' detail in EVENT" ) if "transaction_hash" in details: detail_transaction_hash = details["transaction_hash"] if type(detail_transaction_hash) != str: raise ProtocolError( - "invalid type {0} for 'transaction_hash' detail in EVENT".format( - type(detail_transaction_hash) - ) + f"invalid type {type(detail_transaction_hash)} for 'transaction_hash' detail in EVENT" ) transaction_hash = detail_transaction_hash @@ -6051,9 +5928,7 @@ def parse(wmsg): x_acknowledged_delivery = details["x_acknowledged_delivery"] if type(x_acknowledged_delivery) != bool: raise ProtocolError( - "invalid type {0} for 'x_acknowledged_delivery' detail in EVENT".format( - type(x_acknowledged_delivery) - ) + f"invalid type {type(x_acknowledged_delivery)} for 'x_acknowledged_delivery' detail in EVENT" ) if "forward_for" in details: @@ -6244,7 +6119,7 @@ def parse(wmsg): if len(wmsg) != 2: raise ProtocolError( - "invalid message length {0} for EVENT_RECEIVED".format(len(wmsg)) + f"invalid message length {len(wmsg)} for EVENT_RECEIVED" ) publication = check_or_raise_id(wmsg[1], "'publication' in EVENT_RECEIVED") @@ -6741,7 +6616,7 @@ def parse(wmsg): assert len(wmsg) > 0 and wmsg[0] == Call.MESSAGE_TYPE if len(wmsg) not in (4, 5, 6): - raise ProtocolError("invalid message length {0} for CALL".format(len(wmsg))) + raise ProtocolError(f"invalid message length {len(wmsg)} for CALL") request = check_or_raise_id(wmsg[1], "'request' in CALL") options = check_or_raise_extra(wmsg[2], "'options' in CALL") @@ -6760,23 +6635,19 @@ def parse(wmsg): enc_algo = options.get("enc_algo", None) if enc_algo and not is_valid_enc_algo(enc_algo): raise ProtocolError( - "invalid value {0} for 'enc_algo' detail in CALL".format(enc_algo) + f"invalid value {enc_algo} for 'enc_algo' detail in CALL" ) enc_key = options.get("enc_key", None) if enc_key and type(enc_key) != str: raise ProtocolError( - "invalid type {0} for 'enc_key' detail in CALL".format( - type(enc_key) - ) + f"invalid type {type(enc_key)} for 'enc_key' detail in CALL" ) enc_serializer = options.get("enc_serializer", None) if enc_serializer and not is_valid_enc_serializer(enc_serializer): raise ProtocolError( - "invalid value {0} for 'enc_serializer' detail in CALL".format( - enc_serializer - ) + f"invalid value {enc_serializer} for 'enc_serializer' detail in CALL" ) else: @@ -6784,14 +6655,14 @@ def parse(wmsg): args = wmsg[4] if args is not None and type(args) != list: raise ProtocolError( - "invalid type {0} for 'args' in CALL".format(type(args)) + f"invalid type {type(args)} for 'args' in CALL" ) if len(wmsg) > 5: kwargs = wmsg[5] if type(kwargs) != dict: raise ProtocolError( - "invalid type {0} for 'kwargs' in CALL".format(type(kwargs)) + f"invalid type {type(kwargs)} for 'kwargs' in CALL" ) timeout = None @@ -6806,16 +6677,12 @@ def parse(wmsg): option_timeout = options["timeout"] if type(option_timeout) != int: raise ProtocolError( - "invalid type {0} for 'timeout' option in CALL".format( - type(option_timeout) - ) + f"invalid type {type(option_timeout)} for 'timeout' option in CALL" ) if option_timeout < 0: raise ProtocolError( - "invalid value {0} for 'timeout' option in CALL".format( - option_timeout - ) + f"invalid value {option_timeout} for 'timeout' option in CALL" ) timeout = option_timeout @@ -6824,9 +6691,7 @@ def parse(wmsg): option_receive_progress = options["receive_progress"] if type(option_receive_progress) != bool: raise ProtocolError( - "invalid type {0} for 'receive_progress' option in CALL".format( - type(option_receive_progress) - ) + f"invalid type {type(option_receive_progress)} for 'receive_progress' option in CALL" ) receive_progress = option_receive_progress @@ -6835,9 +6700,7 @@ def parse(wmsg): option_transaction_hash = options["transaction_hash"] if type(option_transaction_hash) != str: raise ProtocolError( - "invalid type {0} for 'transaction_hash' detail in CALL".format( - type(option_transaction_hash) - ) + f"invalid type {type(option_transaction_hash)} for 'transaction_hash' detail in CALL" ) transaction_hash = option_transaction_hash @@ -6846,9 +6709,7 @@ def parse(wmsg): option_caller = options["caller"] if type(option_caller) != int: raise ProtocolError( - "invalid type {0} for 'caller' detail in CALL".format( - type(option_caller) - ) + f"invalid type {type(option_caller)} for 'caller' detail in CALL" ) caller = option_caller @@ -6857,9 +6718,7 @@ def parse(wmsg): option_caller_authid = options["caller_authid"] if type(option_caller_authid) != str: raise ProtocolError( - "invalid type {0} for 'caller_authid' detail in CALL".format( - type(option_caller_authid) - ) + f"invalid type {type(option_caller_authid)} for 'caller_authid' detail in CALL" ) caller_authid = option_caller_authid @@ -6868,9 +6727,7 @@ def parse(wmsg): option_caller_authrole = options["caller_authrole"] if type(option_caller_authrole) != str: raise ProtocolError( - "invalid type {0} for 'caller_authrole' detail in CALL".format( - type(option_caller_authrole) - ) + f"invalid type {type(option_caller_authrole)} for 'caller_authrole' detail in CALL" ) caller_authrole = option_caller_authrole @@ -7109,7 +6966,7 @@ def parse(wmsg): if len(wmsg) != 3: raise ProtocolError( - "invalid message length {0} for CANCEL".format(len(wmsg)) + f"invalid message length {len(wmsg)} for CANCEL" ) request = check_or_raise_id(wmsg[1], "'request' in CANCEL") @@ -7124,16 +6981,12 @@ def parse(wmsg): option_mode = options["mode"] if type(option_mode) != str: raise ProtocolError( - "invalid type {0} for 'mode' option in CANCEL".format( - type(option_mode) - ) + f"invalid type {type(option_mode)} for 'mode' option in CANCEL" ) if option_mode not in [Cancel.SKIP, Cancel.KILLNOWAIT, Cancel.KILL]: raise ProtocolError( - "invalid value '{0}' for 'mode' option in CANCEL".format( - option_mode - ) + f"invalid value '{option_mode}' for 'mode' option in CANCEL" ) mode = option_mode @@ -7576,7 +7429,7 @@ def parse(wmsg): if len(wmsg) not in (3, 4, 5): raise ProtocolError( - "invalid message length {0} for RESULT".format(len(wmsg)) + f"invalid message length {len(wmsg)} for RESULT" ) request = check_or_raise_id(wmsg[1], "'request' in RESULT") @@ -7600,23 +7453,19 @@ def parse(wmsg): enc_algo = details.get("enc_algo", None) if enc_algo and not is_valid_enc_algo(enc_algo): raise ProtocolError( - "invalid value {0} for 'enc_algo' detail in RESULT".format(enc_algo) + f"invalid value {enc_algo} for 'enc_algo' detail in RESULT" ) enc_key = details.get("enc_key", None) if enc_key and type(enc_key) != str: raise ProtocolError( - "invalid type {0} for 'enc_key' detail in RESULT".format( - type(enc_key) - ) + f"invalid type {type(enc_key)} for 'enc_key' detail in RESULT" ) enc_serializer = details.get("enc_serializer", None) if enc_serializer and not is_valid_enc_serializer(enc_serializer): raise ProtocolError( - "invalid value {0} for 'enc_serializer' detail in RESULT".format( - enc_serializer - ) + f"invalid value {enc_serializer} for 'enc_serializer' detail in RESULT" ) else: @@ -7624,23 +7473,21 @@ def parse(wmsg): args = wmsg[3] if args is not None and type(args) != list: raise ProtocolError( - "invalid type {0} for 'args' in RESULT".format(type(args)) + f"invalid type {type(args)} for 'args' in RESULT" ) if len(wmsg) > 4: kwargs = wmsg[4] if type(kwargs) != dict: raise ProtocolError( - "invalid type {0} for 'kwargs' in RESULT".format(type(kwargs)) + f"invalid type {type(kwargs)} for 'kwargs' in RESULT" ) if "progress" in details: detail_progress = details["progress"] if type(detail_progress) != bool: raise ProtocolError( - "invalid type {0} for 'progress' option in RESULT".format( - type(detail_progress) - ) + f"invalid type {type(detail_progress)} for 'progress' option in RESULT" ) progress = detail_progress @@ -7649,9 +7496,7 @@ def parse(wmsg): detail_callee = details["callee"] if type(detail_callee) != int: raise ProtocolError( - "invalid type {0} for 'callee' detail in RESULT".format( - type(detail_callee) - ) + f"invalid type {type(detail_callee)} for 'callee' detail in RESULT" ) callee = detail_callee @@ -7660,9 +7505,7 @@ def parse(wmsg): detail_callee_authid = details["callee_authid"] if type(detail_callee_authid) != str: raise ProtocolError( - "invalid type {0} for 'callee_authid' detail in RESULT".format( - type(detail_callee_authid) - ) + f"invalid type {type(detail_callee_authid)} for 'callee_authid' detail in RESULT" ) callee_authid = detail_callee_authid @@ -7671,9 +7514,7 @@ def parse(wmsg): detail_callee_authrole = details["callee_authrole"] if type(detail_callee_authrole) != str: raise ProtocolError( - "invalid type {0} for 'callee_authrole' detail in RESULT".format( - type(detail_callee_authrole) - ) + f"invalid type {type(detail_callee_authrole)} for 'callee_authrole' detail in RESULT" ) callee_authrole = detail_callee_authrole @@ -7993,7 +7834,7 @@ def parse(wmsg): if len(wmsg) != 4: raise ProtocolError( - "invalid message length {0} for REGISTER".format(len(wmsg)) + f"invalid message length {len(wmsg)} for REGISTER" ) request = check_or_raise_id(wmsg[1], "'request' in REGISTER") @@ -8009,9 +7850,7 @@ def parse(wmsg): option_match = options["match"] if type(option_match) != str: raise ProtocolError( - "invalid type {0} for 'match' option in REGISTER".format( - type(option_match) - ) + f"invalid type {type(option_match)} for 'match' option in REGISTER" ) if option_match not in [ @@ -8020,9 +7859,7 @@ def parse(wmsg): Register.MATCH_WILDCARD, ]: raise ProtocolError( - "invalid value {0} for 'match' option in REGISTER".format( - option_match - ) + f"invalid value {option_match} for 'match' option in REGISTER" ) match = option_match @@ -8053,9 +7890,7 @@ def parse(wmsg): option_invoke = options["invoke"] if type(option_invoke) != str: raise ProtocolError( - "invalid type {0} for 'invoke' option in REGISTER".format( - type(option_invoke) - ) + f"invalid type {type(option_invoke)} for 'invoke' option in REGISTER" ) if option_invoke not in [ @@ -8066,9 +7901,7 @@ def parse(wmsg): Register.INVOKE_RANDOM, ]: raise ProtocolError( - "invalid value {0} for 'invoke' option in REGISTER".format( - option_invoke - ) + f"invalid value {option_invoke} for 'invoke' option in REGISTER" ) invoke = option_invoke @@ -8077,16 +7910,12 @@ def parse(wmsg): options_concurrency = options["concurrency"] if type(options_concurrency) != int: raise ProtocolError( - "invalid type {0} for 'concurrency' option in REGISTER".format( - type(options_concurrency) - ) + f"invalid type {type(options_concurrency)} for 'concurrency' option in REGISTER" ) if options_concurrency < 1: raise ProtocolError( - "invalid value {0} for 'concurrency' option in REGISTER".format( - options_concurrency - ) + f"invalid value {options_concurrency} for 'concurrency' option in REGISTER" ) concurrency = options_concurrency @@ -8094,9 +7923,7 @@ def parse(wmsg): options_reregister = options.get("force_reregister", None) if options_reregister not in [True, False, None]: raise ProtocolError( - "invalid type {0} for 'force_reregister option in REGISTER".format( - type(options_reregister) - ) + f"invalid type {type(options_reregister)} for 'force_reregister option in REGISTER" ) if options_reregister is not None: force_reregister = options_reregister @@ -8319,7 +8146,7 @@ def parse(wmsg): if len(wmsg) != 3: raise ProtocolError( - "invalid message length {0} for REGISTERED".format(len(wmsg)) + f"invalid message length {len(wmsg)} for REGISTERED" ) request = check_or_raise_id(wmsg[1], "'request' in REGISTERED") @@ -8457,7 +8284,7 @@ def parse(wmsg): if len(wmsg) not in [3, 4]: raise ProtocolError( - "invalid message length {0} for WAMP UNREGISTER".format(len(wmsg)) + f"invalid message length {len(wmsg)} for WAMP UNREGISTER" ) request = check_or_raise_id(wmsg[1], "'request' in UNREGISTER") @@ -8653,7 +8480,7 @@ def parse(wmsg): if len(wmsg) not in [2, 3]: raise ProtocolError( - "invalid message length {0} for UNREGISTERED".format(len(wmsg)) + f"invalid message length {len(wmsg)} for UNREGISTERED" ) request = check_or_raise_id(wmsg[1], "'request' in UNREGISTERED") @@ -8668,9 +8495,7 @@ def parse(wmsg): details_registration = details["registration"] if type(details_registration) != int: raise ProtocolError( - "invalid type {0} for 'registration' detail in UNREGISTERED".format( - type(details_registration) - ) + f"invalid type {type(details_registration)} for 'registration' detail in UNREGISTERED" ) registration = details_registration @@ -9177,7 +9002,7 @@ def parse(wmsg): if len(wmsg) not in (4, 5, 6): raise ProtocolError( - "invalid message length {0} for INVOCATION".format(len(wmsg)) + f"invalid message length {len(wmsg)} for INVOCATION" ) request = check_or_raise_id(wmsg[1], "'request' in INVOCATION") @@ -9197,25 +9022,19 @@ def parse(wmsg): enc_algo = details.get("enc_algo", None) if enc_algo and not is_valid_enc_algo(enc_algo): raise ProtocolError( - "invalid value {0} for 'enc_algo' detail in INVOCATION".format( - enc_algo - ) + f"invalid value {enc_algo} for 'enc_algo' detail in INVOCATION" ) enc_key = details.get("enc_key", None) if enc_key and type(enc_key) != str: raise ProtocolError( - "invalid type {0} for 'enc_key' detail in INVOCATION".format( - type(enc_key) - ) + f"invalid type {type(enc_key)} for 'enc_key' detail in INVOCATION" ) enc_serializer = details.get("enc_serializer", None) if enc_serializer and not is_valid_enc_serializer(enc_serializer): raise ProtocolError( - "invalid value {0} for 'enc_serializer' detail in INVOCATION".format( - enc_serializer - ) + f"invalid value {enc_serializer} for 'enc_serializer' detail in INVOCATION" ) else: @@ -9223,16 +9042,14 @@ def parse(wmsg): args = wmsg[4] if args is not None and type(args) != list: raise ProtocolError( - "invalid type {0} for 'args' in INVOCATION".format(type(args)) + f"invalid type {type(args)} for 'args' in INVOCATION" ) if len(wmsg) > 5: kwargs = wmsg[5] if type(kwargs) != dict: raise ProtocolError( - "invalid type {0} for 'kwargs' in INVOCATION".format( - type(kwargs) - ) + f"invalid type {type(kwargs)} for 'kwargs' in INVOCATION" ) timeout = None @@ -9248,16 +9065,12 @@ def parse(wmsg): detail_timeout = details["timeout"] if type(detail_timeout) != int: raise ProtocolError( - "invalid type {0} for 'timeout' detail in INVOCATION".format( - type(detail_timeout) - ) + f"invalid type {type(detail_timeout)} for 'timeout' detail in INVOCATION" ) if detail_timeout < 0: raise ProtocolError( - "invalid value {0} for 'timeout' detail in INVOCATION".format( - detail_timeout - ) + f"invalid value {detail_timeout} for 'timeout' detail in INVOCATION" ) timeout = detail_timeout @@ -9266,9 +9079,7 @@ def parse(wmsg): detail_receive_progress = details["receive_progress"] if type(detail_receive_progress) != bool: raise ProtocolError( - "invalid type {0} for 'receive_progress' detail in INVOCATION".format( - type(detail_receive_progress) - ) + f"invalid type {type(detail_receive_progress)} for 'receive_progress' detail in INVOCATION" ) receive_progress = detail_receive_progress @@ -9277,9 +9088,7 @@ def parse(wmsg): detail_caller = details["caller"] if type(detail_caller) != int: raise ProtocolError( - "invalid type {0} for 'caller' detail in INVOCATION".format( - type(detail_caller) - ) + f"invalid type {type(detail_caller)} for 'caller' detail in INVOCATION" ) caller = detail_caller @@ -9288,9 +9097,7 @@ def parse(wmsg): detail_caller_authid = details["caller_authid"] if type(detail_caller_authid) != str: raise ProtocolError( - "invalid type {0} for 'caller_authid' detail in INVOCATION".format( - type(detail_caller_authid) - ) + f"invalid type {type(detail_caller_authid)} for 'caller_authid' detail in INVOCATION" ) caller_authid = detail_caller_authid @@ -9299,9 +9106,7 @@ def parse(wmsg): detail_caller_authrole = details["caller_authrole"] if type(detail_caller_authrole) != str: raise ProtocolError( - "invalid type {0} for 'caller_authrole' detail in INVOCATION".format( - type(detail_caller_authrole) - ) + f"invalid type {type(detail_caller_authrole)} for 'caller_authrole' detail in INVOCATION" ) caller_authrole = detail_caller_authrole @@ -9310,9 +9115,7 @@ def parse(wmsg): detail_procedure = details["procedure"] if type(detail_procedure) != str: raise ProtocolError( - "invalid type {0} for 'procedure' detail in INVOCATION".format( - type(detail_procedure) - ) + f"invalid type {type(detail_procedure)} for 'procedure' detail in INVOCATION" ) procedure = detail_procedure @@ -9321,9 +9124,7 @@ def parse(wmsg): detail_transaction_hash = details["transaction_hash"] if type(detail_transaction_hash) != str: raise ProtocolError( - "invalid type {0} for 'transaction_hash' detail in EVENT".format( - type(detail_transaction_hash) - ) + f"invalid type {type(detail_transaction_hash)} for 'transaction_hash' detail in EVENT" ) transaction_hash = detail_transaction_hash @@ -9594,7 +9395,7 @@ def parse(wmsg): if len(wmsg) != 3: raise ProtocolError( - "invalid message length {0} for INTERRUPT".format(len(wmsg)) + f"invalid message length {len(wmsg)} for INTERRUPT" ) request = check_or_raise_id(wmsg[1], "'request' in INTERRUPT") @@ -9610,16 +9411,12 @@ def parse(wmsg): option_mode = options["mode"] if type(option_mode) != str: raise ProtocolError( - "invalid type {0} for 'mode' option in INTERRUPT".format( - type(option_mode) - ) + f"invalid type {type(option_mode)} for 'mode' option in INTERRUPT" ) if option_mode not in [Interrupt.KILL, Interrupt.KILLNOWAIT]: raise ProtocolError( - "invalid value '{0}' for 'mode' option in INTERRUPT".format( - option_mode - ) + f"invalid value '{option_mode}' for 'mode' option in INTERRUPT" ) mode = option_mode @@ -10075,7 +9872,7 @@ def parse(wmsg): if len(wmsg) not in (3, 4, 5): raise ProtocolError( - "invalid message length {0} for YIELD".format(len(wmsg)) + f"invalid message length {len(wmsg)} for YIELD" ) request = check_or_raise_id(wmsg[1], "'request' in YIELD") @@ -10094,23 +9891,19 @@ def parse(wmsg): enc_algo = options.get("enc_algo", None) if enc_algo and not is_valid_enc_algo(enc_algo): raise ProtocolError( - "invalid value {0} for 'enc_algo' detail in YIELD".format(enc_algo) + f"invalid value {enc_algo} for 'enc_algo' detail in YIELD" ) enc_key = options.get("enc_key", None) if enc_key and type(enc_key) != str: raise ProtocolError( - "invalid type {0} for 'enc_key' detail in YIELD".format( - type(enc_key) - ) + f"invalid type {type(enc_key)} for 'enc_key' detail in YIELD" ) enc_serializer = options.get("enc_serializer", None) if enc_serializer and not is_valid_enc_serializer(enc_serializer): raise ProtocolError( - "invalid value {0} for 'enc_serializer' detail in YIELD".format( - enc_serializer - ) + f"invalid value {enc_serializer} for 'enc_serializer' detail in YIELD" ) else: @@ -10118,14 +9911,14 @@ def parse(wmsg): args = wmsg[3] if args is not None and type(args) != list: raise ProtocolError( - "invalid type {0} for 'args' in YIELD".format(type(args)) + f"invalid type {type(args)} for 'args' in YIELD" ) if len(wmsg) > 4: kwargs = wmsg[4] if type(kwargs) != dict: raise ProtocolError( - "invalid type {0} for 'kwargs' in YIELD".format(type(kwargs)) + f"invalid type {type(kwargs)} for 'kwargs' in YIELD" ) progress = None @@ -10138,9 +9931,7 @@ def parse(wmsg): option_progress = options["progress"] if type(option_progress) != bool: raise ProtocolError( - "invalid type {0} for 'progress' option in YIELD".format( - type(option_progress) - ) + f"invalid type {type(option_progress)} for 'progress' option in YIELD" ) progress = option_progress @@ -10149,9 +9940,7 @@ def parse(wmsg): option_callee = options["callee"] if type(option_callee) != int: raise ProtocolError( - "invalid type {0} for 'callee' detail in YIELD".format( - type(option_callee) - ) + f"invalid type {type(option_callee)} for 'callee' detail in YIELD" ) callee = option_callee @@ -10160,9 +9949,7 @@ def parse(wmsg): option_callee_authid = options["callee_authid"] if type(option_callee_authid) != str: raise ProtocolError( - "invalid type {0} for 'callee_authid' detail in YIELD".format( - type(option_callee_authid) - ) + f"invalid type {type(option_callee_authid)} for 'callee_authid' detail in YIELD" ) callee_authid = option_callee_authid @@ -10171,9 +9958,7 @@ def parse(wmsg): option_callee_authrole = options["callee_authrole"] if type(option_callee_authrole) != str: raise ProtocolError( - "invalid type {0} for 'callee_authrole' detail in YIELD".format( - type(option_callee_authrole) - ) + f"invalid type {type(option_callee_authrole)} for 'callee_authrole' detail in YIELD" ) callee_authrole = option_callee_authrole diff --git a/src/autobahn/wamp/protocol.py b/src/autobahn/wamp/protocol.py index e66912cf2..37843eedf 100644 --- a/src/autobahn/wamp/protocol.py +++ b/src/autobahn/wamp/protocol.py @@ -25,7 +25,8 @@ ############################################################################### import inspect from functools import reduce -from typing import Any, Callable, ClassVar, Dict, List, Optional, Union +from typing import Any, ClassVar, Union +from collections.abc import Callable import txaio @@ -103,40 +104,40 @@ def __init__(self): self.traceback_app = False # mapping of exception classes to list of WAMP error URI patterns - self._ecls_to_uri_pat: Dict[ClassVar, List[uri.Pattern]] = {} + self._ecls_to_uri_pat: dict[ClassVar, list[uri.Pattern]] = {} # mapping of WAMP error URIs to exception classes - self._uri_to_ecls: Dict[str, ClassVar] = { + self._uri_to_ecls: dict[str, ClassVar] = { ApplicationError.INVALID_PAYLOAD: SerializationError, ApplicationError.PAYLOAD_SIZE_EXCEEDED: PayloadExceededError, } # WAMP ITransport (_not_ a Twisted protocol, which is self.transport - when using Twisted) - self._transport: Optional[ITransport] = None + self._transport: ITransport | None = None # session authentication information - self._realm: Optional[str] = None - self._session_id: Optional[int] = None - self._authid: Optional[str] = None - self._authrole: Optional[str] = None - self._authmethod: Optional[str] = None - self._authprovider: Optional[str] = None - self._authextra: Optional[Dict[str, Any]] = None + self._realm: str | None = None + self._session_id: int | None = None + self._authid: str | None = None + self._authrole: str | None = None + self._authmethod: str | None = None + self._authprovider: str | None = None + self._authextra: dict[str, Any] | None = None # set client role features supported and announced - self._session_roles: Dict[str, role.RoleFeatures] = role.DEFAULT_CLIENT_ROLES + self._session_roles: dict[str, role.RoleFeatures] = role.DEFAULT_CLIENT_ROLES # complete session details - self._session_details: Optional[SessionDetails] = None + self._session_details: SessionDetails | None = None # payload transparency codec - self._payload_codec: Optional[IPayloadCodec] = None + self._payload_codec: IPayloadCodec | None = None # generator for WAMP request IDs self._request_id_gen = IdGenerator() @property - def transport(self) -> Optional[ITransport]: + def transport(self) -> ITransport | None: """ Implements :func:`autobahn.wamp.interfaces.ITransportHandler.transport` """ @@ -159,41 +160,41 @@ def is_attached(self) -> bool: return self._session_id is not None and self.is_connected() @property - def session_details(self) -> Optional[SessionDetails]: + def session_details(self) -> SessionDetails | None: """ Implements :func:`autobahn.wamp.interfaces.ISession.session_details` """ return self._session_details @property - def realm(self) -> Optional[str]: + def realm(self) -> str | None: return self._realm @property - def session_id(self) -> Optional[int]: + def session_id(self) -> int | None: return self._session_id @property - def authid(self) -> Optional[str]: + def authid(self) -> str | None: return self._authid @property - def authrole(self) -> Optional[str]: + def authrole(self) -> str | None: return self._authrole @property - def authmethod(self) -> Optional[str]: + def authmethod(self) -> str | None: return self._authmethod @property - def authprovider(self) -> Optional[str]: + def authprovider(self) -> str | None: return self._authprovider @property - def authextra(self) -> Optional[Dict[str, Any]]: + def authextra(self) -> dict[str, Any] | None: return self._authextra - def define(self, exception: Exception, error: Optional[str] = None): + def define(self, exception: Exception, error: str | None = None): """ Implements :func:`autobahn.wamp.interfaces.ISession.define` """ @@ -313,7 +314,7 @@ def _exception_from_message(self, msg): ) enc_err = ApplicationError( ApplicationError.ENC_DECRYPT_ERROR, - "failed to decrypt application payload 1: {}".format(e), + f"failed to decrypt application payload 1: {e}", enc_algo=msg.enc_algo, ) else: @@ -325,9 +326,7 @@ def _exception_from_message(self, msg): ) enc_err = ApplicationError( ApplicationError.ENC_TRUSTED_URI_MISMATCH, - "URI within encrypted payload ('{}') does not match the envelope ('{}')".format( - decrypted_error, msg.error - ), + f"URI within encrypted payload ('{decrypted_error}') does not match the envelope ('{msg.error}')", enc_algo=msg.enc_algo, ) @@ -398,7 +397,7 @@ class ApplicationSession(BaseSession): * :class:`autobahn.wamp.interfaces.ISession` """ - def __init__(self, config: Optional[types.ComponentConfig] = None): + def __init__(self, config: types.ComponentConfig | None = None): """ Implements :func:`autobahn.wamp.interfaces.ISession` """ @@ -412,7 +411,7 @@ def __init__(self, config: Optional[types.ComponentConfig] = None): self._transport_is_closing: bool = False # WAMP application payload codec (e.g. for WAMP-cryptobox E2E) - self._payload_codec: Optional[IPayloadCodec] = None + self._payload_codec: IPayloadCodec | None = None # outstanding requests self._publish_reqs = {} @@ -436,14 +435,14 @@ def config(self) -> types.ComponentConfig: return self._config @public - def set_payload_codec(self, payload_codec: Optional[IPayloadCodec]): + def set_payload_codec(self, payload_codec: IPayloadCodec | None): """ Implements :func:`autobahn.wamp.interfaces.ISession.set_payload_codec` """ self._payload_codec = payload_codec @public - def get_payload_codec(self) -> Optional[IPayloadCodec]: + def get_payload_codec(self) -> IPayloadCodec | None: """ Implements :func:`autobahn.wamp.interfaces.ISession.get_payload_codec` """ @@ -484,13 +483,13 @@ def onConnect(self): def join( self, realm: str, - authmethods: Optional[List[str]] = None, - authid: Optional[str] = None, - authrole: Optional[str] = None, - authextra: Optional[Dict[str, Any]] = None, - resumable: Optional[bool] = None, - resume_session: Optional[int] = None, - resume_token: Optional[str] = None, + authmethods: list[str] | None = None, + authid: str | None = None, + authrole: str | None = None, + authextra: dict[str, Any] | None = None, + resumable: bool | None = None, + resume_session: int | None = None, + resume_token: str | None = None, ): """ Implements :func:`autobahn.wamp.interfaces.ISession.join` @@ -590,15 +589,11 @@ async def _type_check(*args, **kwargs): expected_types = [arg.__name__ for arg in kind.__args__] if not isinstance(arguments[name], kind.__args__): response.append( - "'{}' expected types={} got={}".format( - name, expected_types, type(arguments[name]).__name__ - ) + f"'{name}' expected types={expected_types} got={type(arguments[name]).__name__}" ) elif not isinstance(arguments[name], kind): response.append( - "'{}' expected type={} got={}".format( - name, kind.__name__, type(arguments[name]).__name__ - ) + f"'{name}' expected type={kind.__name__} got={type(arguments[name]).__name__}" ) if response: raise TypeCheckError(", ".join(response)) @@ -626,7 +621,7 @@ def success(res): if res is not None: self.log.debug("Session denied by onWelcome: {res}", res=res) reply = message.Abort( - "wamp.error.cannot_authenticate", "{0}".format(res) + "wamp.error.cannot_authenticate", f"{res}" ) self._transport.send(reply) return @@ -735,7 +730,7 @@ def success(signature): signature = signature.decode("utf8") if type(signature) != str: raise Exception( - "signature must be unicode (was {})".format(type(signature)) + f"signature must be unicode (was {type(signature)})" ) reply = message.Authenticate(signature) self._transport.send(reply) @@ -743,7 +738,7 @@ def success(signature): def error(err): self.onUserError(err, "Authentication failed") reply = message.Abort( - "wamp.error.cannot_authenticate", "{0}".format(err.value) + "wamp.error.cannot_authenticate", f"{err.value}" ) self._transport.send(reply) # fire callback and close the transport @@ -767,9 +762,7 @@ def _error(e): else: raise ProtocolError( - "Received {0} message, and session is not yet established".format( - msg.__class__ - ) + f"Received {msg.__class__} message, and session is not yet established" ) else: @@ -792,9 +785,7 @@ def success(arg): return arg def _error(e): - errmsg = 'While firing onLeave for reason "{0}" and message "{1}"'.format( - msg.reason, msg.message - ) + errmsg = f'While firing onLeave for reason "{msg.reason}" and message "{msg.message}"' return self._swallow_error(e, errmsg) txaio.add_callbacks(d, success, _error) @@ -879,9 +870,7 @@ def _success(_): ) def _error(e): - errmsg = "While firing {0} subscribed under {1}.".format( - handler.fn, msg.subscription - ) + errmsg = f"While firing {handler.fn} subscribed under {msg.subscription}." return self._swallow_error(e, errmsg) future = txaio.as_future( @@ -891,9 +880,7 @@ def _error(e): else: raise ProtocolError( - "EVENT received for non-subscribed subscription ID {0}".format( - msg.subscription - ) + f"EVENT received for non-subscribed subscription ID {msg.subscription}" ) elif isinstance(msg, message.Published): @@ -915,9 +902,7 @@ def _error(e): txaio.resolve(publish_request.on_reply, publication) else: raise ProtocolError( - "PUBLISHED received for non-pending request ID {0}".format( - msg.request - ) + f"PUBLISHED received for non-pending request ID {msg.request}" ) elif isinstance(msg, message.Subscribed): @@ -945,9 +930,7 @@ def _error(e): txaio.resolve(request.on_reply, subscription) else: raise ProtocolError( - "SUBSCRIBED received for non-pending request ID {0}".format( - msg.request - ) + f"SUBSCRIBED received for non-pending request ID {msg.request}" ) elif isinstance(msg, message.Unsubscribed): @@ -972,9 +955,7 @@ def _error(e): txaio.resolve(request.on_reply, 0) else: raise ProtocolError( - "UNSUBSCRIBED received for non-pending request ID {0}".format( - msg.request - ) + f"UNSUBSCRIBED received for non-pending request ID {msg.request}" ) elif isinstance(msg, message.Result): @@ -1012,9 +993,7 @@ def _error(e): ) enc_err = ApplicationError( ApplicationError.ENC_DECRYPT_ERROR, - "failed to decrypt application payload 1: {}".format( - e - ), + f"failed to decrypt application payload 1: {e}", ) else: if proc != decrypted_proc: @@ -1025,9 +1004,7 @@ def _error(e): ) enc_err = ApplicationError( ApplicationError.ENC_TRUSTED_URI_MISMATCH, - "URI within encrypted payload ('{}') does not match the envelope ('{}')".format( - decrypted_proc, proc - ), + f"URI within encrypted payload ('{decrypted_proc}') does not match the envelope ('{proc}')", ) if msg.progress: @@ -1117,25 +1094,19 @@ def _error(fail): txaio.resolve(on_reply, None) else: raise ProtocolError( - "RESULT received for non-pending request ID {0}".format( - msg.request - ) + f"RESULT received for non-pending request ID {msg.request}" ) elif isinstance(msg, message.Invocation): if msg.request in self._invocations: raise ProtocolError( - "INVOCATION received for request ID {0} already invoked".format( - msg.request - ) + f"INVOCATION received for request ID {msg.request} already invoked" ) else: if msg.registration not in self._registrations: raise ProtocolError( - "INVOCATION received for non-registered registration ID {0}".format( - msg.registration - ) + f"INVOCATION received for non-registered registration ID {msg.registration}" ) else: @@ -1171,9 +1142,7 @@ def _error(fail): ) enc_err = ApplicationError( ApplicationError.ENC_DECRYPT_ERROR, - "failed to decrypt INVOCATION payload: {}".format( - e - ), + f"failed to decrypt INVOCATION payload: {e}", ) else: if proc != decrypted_proc: @@ -1185,9 +1154,7 @@ def _error(fail): ) enc_err = ApplicationError( ApplicationError.ENC_TRUSTED_URI_MISMATCH, - "URI within encrypted INVOCATION payload ('{}') does not match the envelope ('{}')".format( - decrypted_proc, proc - ), + f"URI within encrypted INVOCATION payload ('{decrypted_proc}') does not match the envelope ('{proc}')", ) if enc_err: @@ -1336,9 +1303,7 @@ def success(res): if self._transport is None: self.log.debug( - 'Skipping result of "{}", request {} because transport disconnected.'.format( - registration.procedure, msg.request - ) + f'Skipping result of "{registration.procedure}", request {msg.request} because transport disconnected.' ) return @@ -1351,12 +1316,7 @@ def success(res): msg.request, ApplicationError.INVALID_PAYLOAD, args=[ - 'success return value (args={}, kwargs={}) from invoked procedure "{}" could not be serialized: {}'.format( - reply.args, - reply.kwargs, - registration.procedure, - e, - ) + f'success return value (args={reply.args}, kwargs={reply.kwargs}) from invoked procedure "{registration.procedure}" could not be serialized: {e}' ], ) self._transport.send(error_reply) @@ -1368,12 +1328,7 @@ def success(res): msg.request, ApplicationError.PAYLOAD_SIZE_EXCEEDED, args=[ - 'success return value (args={}, kwargs={}) from invoked procedure "{}" exceeds transport size limit: {}'.format( - reply.args, - reply.kwargs, - registration.procedure, - e, - ) + f'success return value (args={reply.args}, kwargs={reply.kwargs}) from invoked procedure "{registration.procedure}" exceeds transport size limit: {e}' ], ) self._transport.send(error_reply) @@ -1409,9 +1364,7 @@ def error(err): msg.request, ApplicationError.INVALID_PAYLOAD, args=[ - 'error return value from invoked procedure "{0}" could not be serialized: {1}'.format( - registration.procedure, e - ) + f'error return value from invoked procedure "{registration.procedure}" could not be serialized: {e}' ], ) self._transport.send(reply) @@ -1423,9 +1376,7 @@ def error(err): msg.request, ApplicationError.PAYLOAD_SIZE_EXCEEDED, args=[ - 'success return value from invoked procedure "{0}" exceeds transport size limit: {1}'.format( - registration.procedure, e - ) + f'success return value from invoked procedure "{registration.procedure}" exceeds transport size limit: {e}' ], ) self._transport.send(reply) @@ -1471,17 +1422,13 @@ def error(err): self._registrations[msg.registration] = registration else: raise ProtocolError( - "REGISTERED received for already existing registration ID {0}".format( - msg.registration - ) + f"REGISTERED received for already existing registration ID {msg.registration}" ) txaio.resolve(request.on_reply, registration) else: raise ProtocolError( - "REGISTERED received for non-pending request ID {0}".format( - msg.request - ) + f"REGISTERED received for non-pending request ID {msg.request}" ) elif isinstance(msg, message.Unregistered): @@ -1494,7 +1441,7 @@ def error(err): except KeyError: raise ProtocolError( "UNREGISTERED received for non-existant registration" - " ID {0}".format(msg.registration) + f" ID {msg.registration}" ) self.log.debug( "Router unregistered procedure '{proc}' with ID {id}", @@ -1519,9 +1466,7 @@ def error(err): txaio.resolve(request.on_reply) else: raise ProtocolError( - "UNREGISTERED received for non-pending request ID {0}".format( - msg.request - ) + f"UNREGISTERED received for non-pending request ID {msg.request}" ) elif isinstance(msg, message.Error): @@ -1575,13 +1520,11 @@ def error(err): txaio.reject(on_reply, self._exception_from_message(msg)) else: raise ProtocolError( - "WampAppSession.onMessage(): ERROR received for non-pending request_type {0} and request ID {1}".format( - msg.request_type, msg.request - ) + f"WampAppSession.onMessage(): ERROR received for non-pending request_type {msg.request_type} and request ID {msg.request}" ) else: - raise ProtocolError("Unexpected message {0}".format(msg.__class__)) + raise ProtocolError(f"Unexpected message {msg.__class__}") @public def onClose(self, wasClean): @@ -1594,9 +1537,7 @@ def onClose(self, wasClean): # fire callback and close the transport details = types.CloseDetails( reason=types.CloseDetails.REASON_TRANSPORT_LOST, - message="WAMP transport was lost without closing the session {} before".format( - self._session_id - ), + message=f"WAMP transport was lost without closing the session {self._session_id} before", ) d = txaio.as_future(self.onLeave, details) @@ -1643,7 +1584,7 @@ def onJoin(self, details: SessionDetails): """ @public - def onWelcome(self, welcome: message.Welcome) -> Optional[str]: + def onWelcome(self, welcome: message.Welcome) -> str | None: """ Implements :meth:`autobahn.wamp.interfaces.ISession.onWelcome` """ @@ -1712,7 +1653,7 @@ def disconnect(_): return d @public - def leave(self, reason: Optional[str] = None, message: Optional[str] = None): + def leave(self, reason: str | None = None, message: str | None = None): """ Implements :meth:`autobahn.wamp.interfaces.ISession.leave` """ @@ -1750,7 +1691,7 @@ def onDisconnect(self): # def publish(self, topic: str, *args: Optional[List[Any]], **kwargs: Optional[Dict[str, Any]]) -> Optional[Publication]: @public - def publish(self, topic: str, *args, **kwargs) -> Optional[Publication]: + def publish(self, topic: str, *args, **kwargs) -> Publication | None: """ Implements :meth:`autobahn.wamp.interfaces.IPublisher.publish` """ @@ -1760,7 +1701,7 @@ def publish(self, topic: str, *args, **kwargs) -> Optional[Publication]: message.check_or_raise_uri( topic, - message="{}.publish()".format(self.__class__.__name__), + message=f"{self.__class__.__name__}.publish()", strict=False, allow_empty_components=False, allow_none=False, @@ -1850,11 +1791,11 @@ def publish(self, topic: str, *args, **kwargs) -> Optional[Publication]: @public def subscribe( self, - handler: Union[Callable, Any], - topic: Optional[str] = None, - options: Optional[SubscribeOptions] = None, - check_types: Optional[bool] = None, - ) -> Union[Subscription, List[Subscription]]: + handler: Callable | Any, + topic: str | None = None, + options: SubscribeOptions | None = None, + check_types: bool | None = None, + ) -> Subscription | list[Subscription]: """ Implements :meth:`autobahn.wamp.interfaces.ISubscriber.subscribe` """ @@ -1870,7 +1811,7 @@ def subscribe( def _subscribe(obj, fn, topic, options, check_types): message.check_or_raise_uri( topic, - message="{}.subscribe()".format(self.__class__.__name__), + message=f"{self.__class__.__name__}.subscribe()", strict=False, allow_empty_components=True, allow_none=False, @@ -1967,7 +1908,7 @@ def _unsubscribe(self, subscription): return txaio.create_future_success(scount) @public - def call(self, procedure: str, *args, **kwargs) -> Union[Any, CallResult]: + def call(self, procedure: str, *args, **kwargs) -> Any | CallResult: """ Implements :meth:`autobahn.wamp.interfaces.ICaller.call` @@ -1984,7 +1925,7 @@ def call(self, procedure: str, *args, **kwargs) -> Union[Any, CallResult]: message.check_or_raise_uri( procedure, - message="{}.call()".format(self.__class__.__name__), + message=f"{self.__class__.__name__}.call()", strict=False, allow_empty_components=False, allow_none=False, @@ -2083,12 +2024,12 @@ def canceller(d): @public def register( self, - endpoint: Union[Callable, Any], - procedure: Optional[str] = None, - options: Optional[RegisterOptions] = None, - prefix: Optional[str] = None, - check_types: Optional[bool] = None, - ) -> Union[Registration, List[Registration]]: + endpoint: Callable | Any, + procedure: str | None = None, + options: RegisterOptions | None = None, + prefix: str | None = None, + check_types: bool | None = None, + ) -> Registration | list[Registration]: """ Implements :meth:`autobahn.wamp.interfaces.ICallee.register` """ @@ -2102,7 +2043,7 @@ def register( def _register(obj, fn, procedure, options, check_types): message.check_or_raise_uri( procedure, - message="{}.register()".format(self.__class__.__name__), + message=f"{self.__class__.__name__}.register()", strict=False, allow_empty_components=True, allow_none=False, @@ -2114,7 +2055,7 @@ def _register(obj, fn, procedure, options, check_types): fn = self.type_check(fn) endpoint_obj = Endpoint(fn, obj, options.details_arg if options else None) if prefix is not None: - procedure = "{}{}".format(prefix, procedure) + procedure = f"{prefix}{procedure}" self._register_reqs[request_id] = RegisterRequest( request_id, on_reply, procedure, endpoint_obj ) @@ -2231,9 +2172,7 @@ def onChallenge(self, challenge): authenticator = self._authenticators[challenge.method] except KeyError: raise RuntimeError( - "Received challenge for unknown authmethod '{}' [authenticators={}]".format( - challenge.method, str(sorted(self._authenticators.keys())) - ) + f"Received challenge for unknown authmethod '{challenge.method}' [authenticators={str(sorted(self._authenticators.keys()))}]" ) return authenticator.on_challenge(self, challenge) @@ -2245,9 +2184,7 @@ def onWelcome(self, msg): authenticator = self._authenticators[msg.authmethod] except KeyError: raise RuntimeError( - "Received onWelcome for unknown authmethod '{}' [authenticators={}]".format( - msg.authmethod, str(sorted(self._authenticators.keys())) - ) + f"Received onWelcome for unknown authmethod '{msg.authmethod}' [authenticators={str(sorted(self._authenticators.keys()))}]" ) return authenticator.on_welcome(self, msg.authextra) @@ -2298,11 +2235,7 @@ def at_most_one(name): for k, v in merged.items(): if k in authextra and authextra[k] != v: raise ValueError( - "Inconsistent authextra values for '{}': '{}' vs '{}'".format( - k, - v, - authextra[k], - ) + f"Inconsistent authextra values for '{k}': '{v}' vs '{authextra[k]}'" ) # validation complete, add it @@ -2336,7 +2269,7 @@ def first_value_for(k): if k in authextra: return authextra[k] # "can't" happen - raise ValueError("No values for '{}'".format(k)) + raise ValueError(f"No values for '{k}'") return {k: first_value_for(k) for k in unique_keys} @@ -2360,7 +2293,7 @@ def on_disconnect(self): ISession.abc_register(ApplicationSession) -class ApplicationSessionFactory(object): +class ApplicationSessionFactory: """ WAMP endpoint session factory. """ diff --git a/src/autobahn/wamp/request.py b/src/autobahn/wamp/request.py index c072e3942..774d1b837 100644 --- a/src/autobahn/wamp/request.py +++ b/src/autobahn/wamp/request.py @@ -41,7 +41,7 @@ ) -class Publication(object): +class Publication: """ Object representing a publication (feedback from publishing an event when doing an acknowledged publish). @@ -62,12 +62,10 @@ def __init__(self, publication_id, was_encrypted): self.was_encrypted = was_encrypted def __str__(self): - return "Publication(id={0}, was_encrypted={1})".format( - self.id, self.was_encrypted - ) + return f"Publication(id={self.id}, was_encrypted={self.was_encrypted})" -class Subscription(object): +class Subscription: """ Object representing a handler subscription. """ @@ -105,10 +103,10 @@ def unsubscribe(self): raise Exception("subscription no longer active") def __str__(self): - return "Subscription(id={0}, is_active={1})".format(self.id, self.active) + return f"Subscription(id={self.id}, is_active={self.active})" -class Handler(object): +class Handler: """ Object representing an event handler attached to a subscription. """ @@ -132,7 +130,7 @@ def __init__(self, fn, obj=None, details_arg=None): self.details_arg = details_arg -class Registration(object): +class Registration: """ Object representing a registration. """ @@ -168,12 +166,10 @@ def unregister(self): raise Exception("registration no longer active") def __str__(self): - return 'Registration(id={0}, is_active={1}, procedure="{2}")'.format( - self.id, self.active, self.procedure - ) + return f'Registration(id={self.id}, is_active={self.active}, procedure="{self.procedure}")' -class Endpoint(object): +class Endpoint: """ Object representing an procedure endpoint attached to a registration. """ @@ -197,7 +193,7 @@ def __init__(self, fn, obj=None, details_arg=None): self.details_arg = details_arg -class Request(object): +class Request: """ Object representing an outstanding request, such as for subscribe/unsubscribe, register/unregister or call/publish. diff --git a/src/autobahn/wamp/role.py b/src/autobahn/wamp/role.py index 235ca262c..03256e58d 100644 --- a/src/autobahn/wamp/role.py +++ b/src/autobahn/wamp/role.py @@ -57,7 +57,7 @@ def __repr__(self): for k, v in self.__dict__.items(): if v is not None: configured_options[k] = v - return "{0}({1})".format( + return "{}({})".format( self.ROLE, ", ".join([k + "=" + str(v) for k, v in configured_options.items()]), ) @@ -68,9 +68,7 @@ def _check_all_bool(self): if not k.startswith("_") and k != "ROLE": if getattr(self, k) is not None and type(getattr(self, k)) != bool: raise ProtocolError( - "invalid type {0} for feature '{1}' for role '{2}'".format( - getattr(self, k), k, self.ROLE - ) + f"invalid type {getattr(self, k)} for feature '{k}' for role '{self.ROLE}'" ) diff --git a/src/autobahn/wamp/serializer.py b/src/autobahn/wamp/serializer.py index 18128e794..d585e0d9a 100644 --- a/src/autobahn/wamp/serializer.py +++ b/src/autobahn/wamp/serializer.py @@ -31,7 +31,6 @@ import re import struct from binascii import a2b_hex, b2a_hex -from typing import List, Optional, Tuple from txaio import time_ns @@ -48,7 +47,7 @@ SERID_TO_SER = {} -class Serializer(object): +class Serializer: """ Base class for WAMP serializers. A WAMP serializer is the core glue between parsed WAMP message objects and the bytes on wire (the transport). @@ -251,7 +250,7 @@ def stats(self, reset=True, details=False): self._stats_reset = time_ns() return data - def serialize(self, msg: IMessage) -> Tuple[bytes, bool]: + def serialize(self, msg: IMessage) -> tuple[bytes, bool]: """ Implements :func:`autobahn.wamp.interfaces.ISerializer.serialize` """ @@ -298,25 +297,21 @@ def serialize_payload(self, data): return payload_ser.serialize(data) def unserialize( - self, payload: bytes, isBinary: Optional[bool] = None - ) -> List[IMessage]: + self, payload: bytes, isBinary: bool | None = None + ) -> list[IMessage]: """ Implements :func:`autobahn.wamp.interfaces.ISerializer.unserialize` """ if isBinary is not None: if isBinary != self._serializer.BINARY: raise ProtocolError( - "invalid serialization of WAMP message (binary {0}, but expected {1})".format( - isBinary, self._serializer.BINARY - ) + f"invalid serialization of WAMP message (binary {isBinary}, but expected {self._serializer.BINARY})" ) try: raw_msgs = self._serializer.unserialize(payload) except Exception as e: raise ProtocolError( - "invalid serialization of WAMP message: {0} {1}".format( - type(e).__name__, e - ) + f"invalid serialization of WAMP message: {type(e).__name__} {e}" ) if self._serializer.NAME == "flatbuffers": @@ -326,7 +321,7 @@ def unserialize( for raw_msg in raw_msgs: if type(raw_msg) != list: raise ProtocolError( - "invalid type {0} for WAMP message".format(type(raw_msg)) + f"invalid type {type(raw_msg)} for WAMP message" ) if len(raw_msg) == 0: @@ -336,16 +331,14 @@ def unserialize( if type(message_type) != int: raise ProtocolError( - "invalid type {0} for WAMP message type".format( - type(message_type) - ) + f"invalid type {type(message_type)} for WAMP message type" ) Klass = self.MESSAGE_TYPE_MAP.get(message_type) if Klass is None: raise ProtocolError( - "invalid WAMP message type {0}".format(message_type) + f"invalid WAMP message type {message_type}" ) # this might again raise `ProtocolError` .. @@ -511,7 +504,7 @@ def _dumps(obj, use_binary_hex_encoding=False): _json = json -class JsonObjectSerializer(object): +class JsonObjectSerializer: JSON_MODULE = _json """ The JSON module used (now only stdlib). @@ -670,7 +663,7 @@ def __init__( if _HAS_MSGPACK: - class MsgPackObjectSerializer(object): + class MsgPackObjectSerializer: NAME = "msgpack" MSGPACK_MODULE = _msgpack @@ -795,7 +788,7 @@ def __init__(self, batched=False): if _HAS_CBOR: - class CBORObjectSerializer(object): + class CBORObjectSerializer: """ CBOR serializer based on `cbor2 `_. @@ -922,7 +915,7 @@ def __init__(self, batched=False): else: # print('Notice: Autobahn is using ubjson module for UBJSON serialization') - class UBJSONObjectSerializer(object): + class UBJSONObjectSerializer: NAME = "ubjson" UBJSON_MODULE = ubjson @@ -1043,7 +1036,7 @@ def __init__(self, batched=False): if _HAS_FLATBUFFERS: - class FlatBuffersObjectSerializer(object): + class FlatBuffersObjectSerializer: NAME = "flatbuffers" FLATBUFFERS_MODULE = flatbuffers @@ -1123,9 +1116,7 @@ def unserialize(self, payload): return [msg] else: raise NotImplementedError( - "message type {} not yet implemented for WAMP-FlatBuffers".format( - msg_type - ) + f"message type {msg_type} not yet implemented for WAMP-FlatBuffers" ) IObjectSerializer.register(FlatBuffersObjectSerializer) @@ -1203,9 +1194,7 @@ def create_transport_serializer(serializer_id): return SERID_TO_SER[serializer_id](batched=batched) else: raise RuntimeError( - 'could not create serializer for "{}" (available: {})'.format( - serializer_id, sorted(SERID_TO_SER.keys()) - ) + f'could not create serializer for "{serializer_id}" (available: {sorted(SERID_TO_SER.keys())})' ) diff --git a/src/autobahn/wamp/test/test_wamp_component.py b/src/autobahn/wamp/test/test_wamp_component.py index 634b8e07e..a9c383c06 100644 --- a/src/autobahn/wamp/test/test_wamp_component.py +++ b/src/autobahn/wamp/test/test_wamp_component.py @@ -55,9 +55,7 @@ def log(self, *args): else: sargs = "-" - msg = "= : {0:>3} : {1:<20} : {2}".format( - self._logline, self.__class__.__name__, sargs - ) + msg = f"= : {self._logline:>3} : {self.__class__.__name__:<20} : {sargs}" self._logline += 1 print(msg) @@ -74,7 +72,7 @@ def onJoin(self, details): self.log("joined") def add2(x, y): - self.log("add2 invoked: {0}, {1}".format(x, y)) + self.log(f"add2 invoked: {x}, {y}") return x + y yield self.register(add2, "com.mathservice.add2") @@ -90,9 +88,9 @@ def onJoin(self, details): try: res = yield self.call("com.mathservice.add2", 2, 3) except Exception as e: - self.log("call error: {0}".format(e)) + self.log(f"call error: {e}") else: - self.log("call result: {0}".format(res)) + self.log(f"call result: {res}") self.finish() @@ -111,11 +109,11 @@ def add2(a, b): def stars(nick="somebody", stars=0): self.log("stars() is invoked", nick, stars) - return "{0} starred {1}x".format(nick, stars) + return f"{nick} starred {stars}x" def orders(product, limit=5): self.log("orders() is invoked", product, limit) - return ["Product {0}".format(i) for i in range(50)][:limit] + return [f"Product {i}" for i in range(50)][:limit] def arglen(*args, **kwargs): self.log("arglen() is invoked", args, kwargs) @@ -140,37 +138,37 @@ def onJoin(self, details): self.log("Pinged!") res = yield self.call("com.arguments.add2", 2, 3) - self.log("Add2: {0}".format(res)) + self.log(f"Add2: {res}") starred = yield self.call("com.arguments.stars") - self.log("Starred 1: {0}".format(starred)) + self.log(f"Starred 1: {starred}") starred = yield self.call("com.arguments.stars", nick="Homer") - self.log("Starred 2: {0}".format(starred)) + self.log(f"Starred 2: {starred}") starred = yield self.call("com.arguments.stars", stars=5) - self.log("Starred 3: {0}".format(starred)) + self.log(f"Starred 3: {starred}") starred = yield self.call("com.arguments.stars", nick="Homer", stars=5) - self.log("Starred 4: {0}".format(starred)) + self.log(f"Starred 4: {starred}") orders = yield self.call("com.arguments.orders", "coffee") - self.log("Orders 1: {0}".format(orders)) + self.log(f"Orders 1: {orders}") orders = yield self.call("com.arguments.orders", "coffee", limit=10) - self.log("Orders 2: {0}".format(orders)) + self.log(f"Orders 2: {orders}") arglengths = yield self.call("com.arguments.arglen") - self.log("Arglen 1: {0}".format(arglengths)) + self.log(f"Arglen 1: {arglengths}") arglengths = yield self.call("com.arguments.arglen", 1, 2, 3) - self.log("Arglen 1: {0}".format(arglengths)) + self.log(f"Arglen 1: {arglengths}") arglengths = yield self.call("com.arguments.arglen", a=1, b=2, c=3) - self.log("Arglen 2: {0}".format(arglengths)) + self.log(f"Arglen 2: {arglengths}") arglengths = yield self.call("com.arguments.arglen", 1, 2, 3, a=1, b=2, c=3) - self.log("Arglen 3: {0}".format(arglengths)) + self.log(f"Arglen 3: {arglengths}") self.log("finishing") diff --git a/src/autobahn/wamp/test/test_wamp_component_aio.py b/src/autobahn/wamp/test/test_wamp_component_aio.py index 262e4539d..aa119225b 100644 --- a/src/autobahn/wamp/test/test_wamp_component_aio.py +++ b/src/autobahn/wamp/test/test_wamp_component_aio.py @@ -88,7 +88,7 @@ def test_asyncio_component_404(): orig_loop = txaio.config.loop txaio.config.loop = asyncio.get_event_loop() - class FakeTransport(object): + class FakeTransport: def close(self): pass diff --git a/src/autobahn/wamp/test/test_wamp_cryptosign.py b/src/autobahn/wamp/test/test_wamp_cryptosign.py index 307215a5e..e28b697ba 100644 --- a/src/autobahn/wamp/test/test_wamp_cryptosign.py +++ b/src/autobahn/wamp/test/test_wamp_cryptosign.py @@ -168,7 +168,7 @@ def setUp(self): # all tests here fake the use of channel_id_type='tls-unique' with the following channel_id m = hashlib.sha256() - m.update("some TLS message".encode()) + m.update(b"some TLS message") # 62e935ae755f3d48f80d4d59f6121358c435722a67e859cc0caa8b539027f2ff channel_id = m.digest() diff --git a/src/autobahn/wamp/test/test_wamp_message.py b/src/autobahn/wamp/test/test_wamp_message.py index 7f166da7b..2a8eb2d9d 100644 --- a/src/autobahn/wamp/test/test_wamp_message.py +++ b/src/autobahn/wamp/test/test_wamp_message.py @@ -30,7 +30,7 @@ from autobahn.wamp.exception import InvalidUriError, ProtocolError -class Foo(object): +class Foo: pass diff --git a/src/autobahn/wamp/test/test_wamp_protocol.py b/src/autobahn/wamp/test/test_wamp_protocol.py index 19eb55ba3..7cfd521e2 100644 --- a/src/autobahn/wamp/test/test_wamp_protocol.py +++ b/src/autobahn/wamp/test/test_wamp_protocol.py @@ -51,7 +51,7 @@ ) from twisted.trial import unittest - class MockTransport(object): + class MockTransport: def __init__(self, handler): self._log = False self._handler = handler @@ -85,7 +85,7 @@ def drop_registration(self, reg_id): def send(self, msg): if self._log: payload, isbinary = self._serializer.serialize(msg) - print("Send: {0}".format(payload)) + print(f"Send: {payload}") reply = None @@ -183,7 +183,7 @@ def send(self, msg): if reply: if self._log: payload, isbinary = self._serializer.serialize(reply) - print("Receive: {0}".format(payload)) + print(f"Receive: {payload}") self._handler.onMessage(reply) def isOpen(self): diff --git a/src/autobahn/wamp/test/test_wamp_transport_details.py b/src/autobahn/wamp/test/test_wamp_transport_details.py index 37f236084..c6e9c6b0b 100644 --- a/src/autobahn/wamp/test/test_wamp_transport_details.py +++ b/src/autobahn/wamp/test/test_wamp_transport_details.py @@ -135,9 +135,5 @@ def test_channel_typeid(self): channel_framing=channel_framing, channel_serializer=channel_serializer, ) - channel_typeid = "{}-{}-{}".format( - TransportDetails.CHANNEL_TYPE_TO_STR[channel_type], - TransportDetails.CHANNEL_FRAMING_TO_STR[channel_framing], - TransportDetails.CHANNEL_SERIALIZER_TO_STR[channel_serializer], - ) + channel_typeid = f"{TransportDetails.CHANNEL_TYPE_TO_STR[channel_type]}-{TransportDetails.CHANNEL_FRAMING_TO_STR[channel_framing]}-{TransportDetails.CHANNEL_SERIALIZER_TO_STR[channel_serializer]}" self.assertEqual(td.channel_typeid, channel_typeid) diff --git a/src/autobahn/wamp/test/test_wamp_uri_pattern.py b/src/autobahn/wamp/test/test_wamp_uri_pattern.py index f2c12a484..7ab121ed6 100644 --- a/src/autobahn/wamp/test/test_wamp_uri_pattern.py +++ b/src/autobahn/wamp/test/test_wamp_uri_pattern.py @@ -463,7 +463,7 @@ def __init__(self, *args, **kwargs): # 4. we can silently drop unconsumed args/kwargs -class MockSession(object): +class MockSession: def __init__(self): self._ecls_to_uri_pat = {} self._uri_to_ecls = {} @@ -517,7 +517,7 @@ def test_decorate_exception_non_exception(self): def test(): # noinspection PyUnusedLocal @wamp.error("com.test.error") - class Foo(object): + class Foo: pass self.assertRaises(Exception, test) diff --git a/src/autobahn/wamp/types.py b/src/autobahn/wamp/types.py index f6012f1ce..3e01c810f 100644 --- a/src/autobahn/wamp/types.py +++ b/src/autobahn/wamp/types.py @@ -59,7 +59,7 @@ @public -class ComponentConfig(object): +class ComponentConfig: """ WAMP application component configuration. An instance of this class is provided to the constructor of :class:`autobahn.wamp.protocol.ApplicationSession`. @@ -129,18 +129,11 @@ def __init__( self.runner = runner def __str__(self): - return "ComponentConfig(realm=<{}>, extra={}, keyring={}, controller={}, shared={}, runner={})".format( - self.realm, - self.extra, - self.keyring, - self.controller, - self.shared, - self.runner, - ) + return f"ComponentConfig(realm=<{self.realm}>, extra={self.extra}, keyring={self.keyring}, controller={self.controller}, shared={self.shared}, runner={self.runner})" @public -class HelloReturn(object): +class HelloReturn: """ Base class for ``HELLO`` return information. """ @@ -194,14 +187,7 @@ def __init__( self.authextra = authextra def __str__(self): - return "Accept(realm=<{}>, authid=<{}>, authrole=<{}>, authmethod={}, authprovider={}, authextra={})".format( - self.realm, - self.authid, - self.authrole, - self.authmethod, - self.authprovider, - self.authextra, - ) + return f"Accept(realm=<{self.realm}>, authid=<{self.authid}>, authrole=<{self.authrole}>, authmethod={self.authmethod}, authprovider={self.authprovider}, authextra={self.authextra})" @public @@ -231,7 +217,7 @@ def __init__(self, reason="wamp.error.not_authorized", message=None): self.message = message def __str__(self): - return "Deny(reason=<{}>, message='{}')".format(self.reason, self.message) + return f"Deny(reason=<{self.reason}>, message='{self.message}')" @public @@ -262,11 +248,11 @@ def __init__(self, method, extra=None): self.extra = extra or {} def __str__(self): - return "Challenge(method={}, extra={})".format(self.method, self.extra) + return f"Challenge(method={self.method}, extra={self.extra})" @public -class HelloDetails(object): +class HelloDetails: """ Provides details of a WAMP session while still attaching. """ @@ -354,22 +340,11 @@ def __init__( self.resume_token = resume_token def __str__(self): - return "HelloDetails(realm=<{}>, authmethods={}, authid=<{}>, authrole=<{}>, authextra={}, session_roles={}, pending_session={}, resumable={}, resume_session={}, resume_token={})".format( - self.realm, - self.authmethods, - self.authid, - self.authrole, - self.authextra, - self.session_roles, - self.pending_session, - self.resumable, - self.resume_session, - self.resume_token, - ) + return f"HelloDetails(realm=<{self.realm}>, authmethods={self.authmethods}, authid=<{self.authid}>, authrole=<{self.authrole}>, authextra={self.authextra}, session_roles={self.session_roles}, pending_session={self.pending_session}, resumable={self.resumable}, resume_session={self.resume_session}, resume_token={self.resume_token})" @public -class SessionIdent(object): +class SessionIdent: """ WAMP session identification information. @@ -411,9 +386,7 @@ def __init__(self, session=None, authid=None, authrole=None): self.authrole = authrole def __str__(self): - return "SessionIdent(session={}, authid={}, authrole={})".format( - self.session, self.authid, self.authrole - ) + return f"SessionIdent(session={self.session}, authid={self.authid}, authrole={self.authrole})" def marshal(self): obj = { @@ -479,7 +452,7 @@ def from_eventdetails(event_details): @public -class CloseDetails(object): +class CloseDetails: """ Provides details for a WAMP session upon close. @@ -514,13 +487,11 @@ def marshal(self): return obj def __str__(self): - return "CloseDetails(reason=<{}>, message='{}')".format( - self.reason, self.message - ) + return f"CloseDetails(reason=<{self.reason}>, message='{self.message}')" @public -class SubscribeOptions(object): +class SubscribeOptions: """ Used to provide options for subscribing in :meth:`autobahn.wamp.interfaces.ISubscriber.subscribe`. @@ -620,17 +591,11 @@ def message_attr(self): return options def __str__(self): - return "SubscribeOptions(match={}, details={}, details_arg={}, get_retained={}, forward_for={})".format( - self.match, - self.details, - self.details_arg, - self.get_retained, - self.forward_for, - ) + return f"SubscribeOptions(match={self.match}, details={self.details}, details_arg={self.details_arg}, get_retained={self.get_retained}, forward_for={self.forward_for})" @public -class EventDetails(object): +class EventDetails: """ Provides details on an event when calling an event handler previously registered. @@ -732,22 +697,11 @@ def __init__( self.forward_for = forward_for def __str__(self): - return "EventDetails(subscription={}, publication={}, publisher={}, publisher_authid={}, publisher_authrole={}, topic=<{}>, retained={}, transaction_hash={}, enc_algo={}, forward_for={})".format( - self.subscription, - self.publication, - self.publisher, - self.publisher_authid, - self.publisher_authrole, - self.topic, - self.retained, - self.transaction_hash, - self.enc_algo, - self.forward_for, - ) + return f"EventDetails(subscription={self.subscription}, publication={self.publication}, publisher={self.publisher}, publisher_authid={self.publisher_authid}, publisher_authrole={self.publisher_authrole}, topic=<{self.topic}>, retained={self.retained}, transaction_hash={self.transaction_hash}, enc_algo={self.enc_algo}, forward_for={self.forward_for})" @public -class PublishOptions(object): +class PublishOptions: """ Used to provide options for subscribing in :meth:`autobahn.wamp.interfaces.IPublisher.publish`. @@ -876,14 +830,12 @@ def __init__( assert transaction_hash is None or type(transaction_hash) == str assert forward_for is None or type(forward_for) == list, ( - "forward_for, when present, must have list type - was {}".format( - type(forward_for) - ) + f"forward_for, when present, must have list type - was {type(forward_for)}" ) if forward_for: for ff in forward_for: assert type(ff) == dict, ( - "forward_for must be type dict - was {}".format(type(ff)) + f"forward_for must be type dict - was {type(ff)}" ) assert "session" in ff, "forward_for must have session attribute" assert type(ff["session"]) == int, ( @@ -983,23 +935,11 @@ def message_attr(self): return options def __str__(self): - return "PublishOptions(acknowledge={}, exclude_me={}, exclude={}, exclude_authid={}, exclude_authrole={}, eligible={}, eligible_authid={}, eligible_authrole={}, retain={}, transaction_hash={}, forward_for={})".format( - self.acknowledge, - self.exclude_me, - self.exclude, - self.exclude_authid, - self.exclude_authrole, - self.eligible, - self.eligible_authid, - self.eligible_authrole, - self.retain, - self.transaction_hash, - self.forward_for, - ) + return f"PublishOptions(acknowledge={self.acknowledge}, exclude_me={self.exclude_me}, exclude={self.exclude}, exclude_authid={self.exclude_authid}, exclude_authrole={self.exclude_authrole}, eligible={self.eligible}, eligible_authid={self.eligible_authid}, eligible_authrole={self.eligible_authrole}, retain={self.retain}, transaction_hash={self.transaction_hash}, forward_for={self.forward_for})" @public -class RegisterOptions(object): +class RegisterOptions: """ Used to provide options for registering in :meth:`autobahn.wamp.interfaces.ICallee.register`. @@ -1131,19 +1071,11 @@ def message_attr(self): return options def __str__(self): - return "RegisterOptions(match={}, invoke={}, concurrency={}, details={}, details_arg={}, force_reregister={}, forward_for={})".format( - self.match, - self.invoke, - self.concurrency, - self.details, - self.details_arg, - self.force_reregister, - self.forward_for, - ) + return f"RegisterOptions(match={self.match}, invoke={self.invoke}, concurrency={self.concurrency}, details={self.details}, details_arg={self.details_arg}, force_reregister={self.force_reregister}, forward_for={self.forward_for})" @public -class CallDetails(object): +class CallDetails: """ Provides details on a call when an endpoint previously registered is being called and opted to receive call details. @@ -1233,21 +1165,11 @@ def __init__( self.forward_for = forward_for def __str__(self): - return "CallDetails(registration={}, progress={}, caller={}, caller_authid={}, caller_authrole={}, procedure=<{}>, transaction_hash={}, enc_algo={}, forward_for={})".format( - self.registration, - self.progress, - self.caller, - self.caller_authid, - self.caller_authrole, - self.procedure, - self.transaction_hash, - self.enc_algo, - self.forward_for, - ) + return f"CallDetails(registration={self.registration}, progress={self.progress}, caller={self.caller}, caller_authid={self.caller_authid}, caller_authrole={self.caller_authrole}, procedure=<{self.procedure}>, transaction_hash={self.transaction_hash}, enc_algo={self.enc_algo}, forward_for={self.forward_for})" @public -class CallOptions(object): +class CallOptions: """ Used to provide options for calling with :meth:`autobahn.wamp.interfaces.ICaller.call`. """ @@ -1366,20 +1288,11 @@ def message_attr(self): return options def __str__(self): - return "CallOptions(on_progress={}, timeout={}, transaction_hash={}, caller={}, caller_authid={}, caller_authrole={}, forward_for={}, details={})".format( - self.on_progress, - self.timeout, - self.transaction_hash, - self.caller, - self.caller_authid, - self.caller_authrole, - self.forward_for, - self.details, - ) + return f"CallOptions(on_progress={self.on_progress}, timeout={self.timeout}, transaction_hash={self.transaction_hash}, caller={self.caller}, caller_authid={self.caller_authid}, caller_authrole={self.caller_authrole}, forward_for={self.forward_for}, details={self.details})" @public -class CallResult(object): +class CallResult: """ Wrapper for remote procedure call results that contain multiple positional return values or keyword-based return values. @@ -1435,19 +1348,11 @@ def __init__(self, *results, **kwresults): self.kwresults = kwresults def __str__(self): - return "CallResult(results={}, kwresults={}, enc_algo={}, callee={}, callee_authid={}, callee_authrole={}, forward_for={})".format( - self.results, - self.kwresults, - self.enc_algo, - self.callee, - self.callee_authid, - self.callee_authrole, - self.forward_for, - ) + return f"CallResult(results={self.results}, kwresults={self.kwresults}, enc_algo={self.enc_algo}, callee={self.callee}, callee_authid={self.callee_authid}, callee_authrole={self.callee_authrole}, forward_for={self.forward_for})" @public -class EncodedPayload(object): +class EncodedPayload: """ Wrapper holding an encoded application payload when using WAMP payload transparency. """ @@ -1481,7 +1386,7 @@ def __init__(self, payload, enc_algo, enc_serializer=None, enc_key=None): @public -class IPublication(object): +class IPublication: """ Represents a publication of an event. This is used with acknowledged publications. """ @@ -1493,7 +1398,7 @@ def id(self): @public -class ISubscription(object): +class ISubscription: """ Represents a subscription to a topic. """ @@ -1532,7 +1437,7 @@ def unsubscribe(self): @public -class IRegistration(object): +class IRegistration: """ Represents a registration of an endpoint. """ @@ -1571,7 +1476,7 @@ def unregister(self): @public -class TransportDetails(object): +class TransportDetails: """ Details about a WAMP transport used for carrying a WAMP session. WAMP can be communicated over different bidirectional underlying transport mechanisms, such as TCP, TLS, Serial @@ -1764,7 +1669,7 @@ def __ne__(self, other): return not self.__eq__(other) @staticmethod - def parse(data: dict[str, Any]) -> "TransportDetails": + def parse(data: dict[str, Any]) -> TransportDetails: assert type(data) == dict obj = TransportDetails() @@ -1862,16 +1767,12 @@ def parse(data: dict[str, Any]) -> "TransportDetails": for binding_type in data["channel_id"]: if binding_type not in ["tls-unique"]: raise ValueError( - 'invalid binding type "{}" in "channel_id" map'.format( - binding_type - ) + f'invalid binding type "{binding_type}" in "channel_id" map' ) binding_id_hex = data["channel_id"][binding_type] if type(binding_id_hex) != str or len(binding_id_hex) != 64: raise ValueError( - 'invalid binding ID "{}" in "channel_id" map'.format( - binding_id_hex - ) + f'invalid binding ID "{binding_id_hex}" in "channel_id" map' ) binding_id = a2b_hex(binding_id_hex) channel_id[binding_type] = binding_id @@ -1966,11 +1867,7 @@ def channel_typeid(self): :return: """ - return "{}-{}-{}".format( - self.CHANNEL_TYPE_TO_STR[self.channel_type or 0], - self.CHANNEL_FRAMING_TO_STR[self.channel_framing or 0], - self.CHANNEL_SERIALIZER_TO_STR[self.channel_serializer or 0], - ) + return f"{self.CHANNEL_TYPE_TO_STR[self.channel_type or 0]}-{self.CHANNEL_FRAMING_TO_STR[self.channel_framing or 0]}-{self.CHANNEL_SERIALIZER_TO_STR[self.channel_serializer or 0]}" @property def channel_type(self) -> int | None: @@ -2241,7 +2138,7 @@ def http_cbtid(self, value: str | None): @public -class SessionDetails(object): +class SessionDetails: """ Provides details for a WAMP session upon open. @@ -2352,7 +2249,7 @@ def __ne__(self, other): return not self.__eq__(other) @staticmethod - def parse(data: dict[str, Any]) -> "SessionDetails": + def parse(data: dict[str, Any]) -> SessionDetails: """ :param data: @@ -2416,9 +2313,7 @@ def parse(data: dict[str, Any]) -> "SessionDetails": for key in data["authextra"].keys(): if type(key) != str: raise ValueError( - 'key "{}" in authextra must be a string, was {}'.format( - key, type(key) - ) + f'key "{key}" in authextra must be a string, was {type(key)}' ) obj._authextra = data["authextra"] diff --git a/src/autobahn/wamp/uri.py b/src/autobahn/wamp/uri.py index 557ab9ec0..83e8f4691 100644 --- a/src/autobahn/wamp/uri.py +++ b/src/autobahn/wamp/uri.py @@ -82,7 +82,7 @@ def convert_starred_uri(uri: str): @public -class Pattern(object): +class Pattern: """ A WAMP URI Pattern. @@ -128,8 +128,8 @@ def __init__( self, uri: str, target: int, - options: Optional[Union[SubscribeOptions, RegisterOptions]] = None, - check_types: Optional[bool] = None, + options: SubscribeOptions | RegisterOptions | None = None, + check_types: bool | None = None, ): """ @@ -199,7 +199,7 @@ def __init__( # should not arrive here raise TypeError("logic error") - pl.append("(?P<{}>{})".format(name, _URI_COMP_CHARS)) + pl.append(f"(?P<{name}>{_URI_COMP_CHARS})") group_count += 1 continue @@ -210,7 +210,7 @@ def __init__( raise TypeError("invalid URI") nc[name] = str - pl.append("(?P<{}>{})".format(name, _URI_COMP_CHARS)) + pl.append(f"(?P<{name}>{_URI_COMP_CHARS})") group_count += 1 continue @@ -221,7 +221,7 @@ def __init__( if component == "": group_count += 1 - pl.append(r"({})".format(_URI_COMP_CHARS)) + pl.append(rf"({_URI_COMP_CHARS})") nc[group_count] = str continue @@ -334,9 +334,9 @@ def is_exception(self): @public def register( - uri: Optional[str], - options: Optional[RegisterOptions] = None, - check_types: Optional[bool] = None, + uri: str | None, + options: RegisterOptions | None = None, + check_types: bool | None = None, ): """ Decorator for WAMP procedure endpoints. @@ -360,7 +360,7 @@ def register( def decorate(f): assert callable(f) if uri is None: - real_uri = "{}".format(f.__name__) + real_uri = f"{f.__name__}" else: real_uri = uri if not hasattr(f, "_wampuris"): @@ -375,9 +375,9 @@ def decorate(f): @public def subscribe( - uri: Optional[str], - options: Optional[SubscribeOptions] = None, - check_types: Optional[bool] = None, + uri: str | None, + options: SubscribeOptions | None = None, + check_types: bool | None = None, ): """ Decorator for WAMP event handlers. diff --git a/src/autobahn/wamp/websocket.py b/src/autobahn/wamp/websocket.py index b302d6325..61e34aeee 100644 --- a/src/autobahn/wamp/websocket.py +++ b/src/autobahn/wamp/websocket.py @@ -26,7 +26,6 @@ import copy import traceback -from typing import Dict, Optional, Tuple from autobahn.util import hlval from autobahn.wamp.exception import ProtocolError, SerializationError, TransportLost @@ -47,15 +46,15 @@ ) -class WampWebSocketProtocol(object): +class WampWebSocketProtocol: """ Base class for WAMP-over-WebSocket transport mixins. """ - _session: Optional[ISession] = None # default; self.session is set in onOpen - _transport_details: Optional[TransportDetails] = None + _session: ISession | None = None # default; self.session is set in onOpen + _transport_details: TransportDetails | None = None - def _bailout(self, code: int, reason: Optional[str] = None): + def _bailout(self, code: int, reason: str | None = None): self.log.debug( 'Failing WAMP-over-WebSocket transport: code={code}, reason="{reason}"', code=code, @@ -76,13 +75,13 @@ def onOpen(self): self._session.onOpen(self) except Exception as e: self.log.critical("{tb}", tb=traceback.format_exc()) - reason = "WAMP Internal Error ({0})".format(e) + reason = f"WAMP Internal Error ({e})" self._bailout( protocol.WebSocketProtocol.CLOSE_STATUS_CODE_INTERNAL_ERROR, reason=reason, ) - def onClose(self, wasClean: bool, code: int, reason: Optional[str]): + def onClose(self, wasClean: bool, code: int, reason: str | None): """ Callback from :func:`autobahn.websocket.interfaces.IWebSocketChannel.onClose` """ @@ -131,7 +130,7 @@ def onMessage(self, payload: bytes, isBinary: bool): except ProtocolError as e: self.log.critical("{tb}", tb=traceback.format_exc()) - reason = "WAMP Protocol Error ({0})".format(e) + reason = f"WAMP Protocol Error ({e})" self._bailout( protocol.WebSocketProtocol.CLOSE_STATUS_CODE_PROTOCOL_ERROR, reason=reason, @@ -139,7 +138,7 @@ def onMessage(self, payload: bytes, isBinary: bool): except Exception as e: self.log.critical("{tb}", tb=traceback.format_exc()) - reason = "WAMP Internal Error ({0})".format(e) + reason = f"WAMP Internal Error ({e})" self._bailout( protocol.WebSocketProtocol.CLOSE_STATUS_CODE_INTERNAL_ERROR, reason=reason, @@ -170,10 +169,10 @@ def send(self, msg): ) payload, isBinary = self._serializer.serialize(msg) except Exception as e: - self.log.error("WAMP message serialization error: {}".format(e)) + self.log.error(f"WAMP message serialization error: {e}") # all exceptions raised from above should be serialization errors .. raise SerializationError( - "WAMP message serialization error: {0}".format(e) + f"WAMP message serialization error: {e}" ) else: self.sendMessage(payload, isBinary) @@ -187,7 +186,7 @@ def isOpen(self): return self._session is not None @property - def transport_details(self) -> Optional[TransportDetails]: + def transport_details(self) -> TransportDetails | None: """ Implements :func:`autobahn.wamp.interfaces.ITransport.transport_details` """ @@ -215,14 +214,12 @@ def abort(self): ITransport.register(WampWebSocketProtocol) -def parseSubprotocolIdentifier(subprotocol: str) -> Tuple[Optional[int], Optional[str]]: +def parseSubprotocolIdentifier(subprotocol: str) -> tuple[int | None, str | None]: try: s = subprotocol.split(".") if s[0] != "wamp": raise Exception( - 'WAMP WebSocket subprotocol identifier must start with "wamp", not "{}"'.format( - s[0] - ) + f'WAMP WebSocket subprotocol identifier must start with "wamp", not "{s[0]}"' ) version = int(s[1]) serializer_id = ".".join(s[2:]) @@ -240,7 +237,7 @@ class WampWebSocketServerProtocol(WampWebSocketProtocol): def onConnect( self, request: ConnectionRequest - ) -> Tuple[Optional[str], Dict[str, str]]: + ) -> tuple[str | None, dict[str, str]]: """ Callback from :func:`autobahn.websocket.interfaces.IWebSocketChannel.onConnect` """ @@ -294,7 +291,7 @@ def onConnect(self, response: ConnectionResponse): self._serializer = copy.copy(self.factory._serializers[serializer_id]) -class WampWebSocketFactory(object): +class WampWebSocketFactory: """ Base class for WAMP-over-WebSocket transport factory mixins. """ @@ -362,7 +359,7 @@ def __init__(self, factory, serializers=None): for ser in serializers: self._serializers[ser.SERIALIZER_ID] = ser - self._protocols = ["wamp.2.{}".format(ser.SERIALIZER_ID) for ser in serializers] + self._protocols = [f"wamp.2.{ser.SERIALIZER_ID}" for ser in serializers] class WampWebSocketServerFactory(WampWebSocketFactory): diff --git a/src/autobahn/websocket/compress_base.py b/src/autobahn/websocket/compress_base.py index f45154dad..9846509b4 100644 --- a/src/autobahn/websocket/compress_base.py +++ b/src/autobahn/websocket/compress_base.py @@ -33,31 +33,31 @@ ) -class PerMessageCompressOffer(object): +class PerMessageCompressOffer: """ Base class for WebSocket compression parameter client offers. """ -class PerMessageCompressOfferAccept(object): +class PerMessageCompressOfferAccept: """ Base class for WebSocket compression parameter client offer accepts by the server. """ -class PerMessageCompressResponse(object): +class PerMessageCompressResponse: """ Base class for WebSocket compression parameter server responses. """ -class PerMessageCompressResponseAccept(object): +class PerMessageCompressResponseAccept: """ Base class for WebSocket compression parameter server response accepts by client. """ -class PerMessageCompress(object): +class PerMessageCompress: """ Base class for WebSocket compression negotiated parameters. """ diff --git a/src/autobahn/websocket/compress_brotli.py b/src/autobahn/websocket/compress_brotli.py index 25cc77bd2..a5154456c 100644 --- a/src/autobahn/websocket/compress_brotli.py +++ b/src/autobahn/websocket/compress_brotli.py @@ -49,7 +49,7 @@ ) -class PerMessageBrotliMixin(object): +class PerMessageBrotliMixin: """ Mixin class for this extension. """ @@ -85,8 +85,7 @@ def parse(cls, params): for p in params: if len(params[p]) > 1: raise Exception( - "multiple occurrence of extension parameter '%s' for extension '%s'" - % (p, cls.EXTENSION_NAME) + f"multiple occurrence of extension parameter '{p}' for extension '{cls.EXTENSION_NAME}'" ) val = params[p][0] @@ -95,8 +94,7 @@ def parse(cls, params): # noinspection PySimplifyBooleanCheck if val is not True: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: accept_no_context_takeover = True @@ -105,16 +103,14 @@ def parse(cls, params): # noinspection PySimplifyBooleanCheck if val is not True: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: request_no_context_takeover = True else: raise Exception( - "illegal extension parameter '%s' for extension '%s'" - % (p, cls.EXTENSION_NAME) + f"illegal extension parameter '{p}' for extension '{cls.EXTENSION_NAME}'" ) offer = cls(accept_no_context_takeover, request_no_context_takeover) @@ -132,16 +128,14 @@ def __init__( """ if type(accept_no_context_takeover) != bool: raise Exception( - "invalid type %s for accept_no_context_takeover" - % type(accept_no_context_takeover) + f"invalid type {type(accept_no_context_takeover)} for accept_no_context_takeover" ) self.accept_no_context_takeover = accept_no_context_takeover if type(request_no_context_takeover) != bool: raise Exception( - "invalid type %s for request_no_context_takeover" - % type(request_no_context_takeover) + f"invalid type {type(request_no_context_takeover)} for request_no_context_takeover" ) self.request_no_context_takeover = request_no_context_takeover @@ -181,8 +175,7 @@ def __repr__(self): :rtype: str """ return ( - "PerMessageBrotliOffer(accept_no_context_takeover = %s, request_no_context_takeover = %s)" - % (self.accept_no_context_takeover, self.request_no_context_takeover) + f"PerMessageBrotliOffer(accept_no_context_takeover = {self.accept_no_context_takeover}, request_no_context_takeover = {self.request_no_context_takeover})" ) @@ -205,20 +198,18 @@ def __init__( :type no_context_takeover: bool """ if not isinstance(offer, PerMessageBrotliOffer): - raise Exception("invalid type %s for offer" % type(offer)) + raise Exception(f"invalid type {type(offer)} for offer") self.offer = offer if type(request_no_context_takeover) != bool: raise Exception( - "invalid type %s for request_no_context_takeover" - % type(request_no_context_takeover) + f"invalid type {type(request_no_context_takeover)} for request_no_context_takeover" ) if request_no_context_takeover and not offer.accept_no_context_takeover: raise Exception( - "invalid value %s for request_no_context_takeover - feature unsupported by client" - % request_no_context_takeover + f"invalid value {request_no_context_takeover} for request_no_context_takeover - feature unsupported by client" ) self.request_no_context_takeover = request_no_context_takeover @@ -226,14 +217,12 @@ def __init__( if no_context_takeover is not None: if type(no_context_takeover) != bool: raise Exception( - "invalid type %s for no_context_takeover" - % type(no_context_takeover) + f"invalid type {type(no_context_takeover)} for no_context_takeover" ) if offer.request_no_context_takeover and not no_context_takeover: raise Exception( - "invalid value %s for no_context_takeover - client requested feature" - % no_context_takeover + f"invalid value {no_context_takeover} for no_context_takeover - client requested feature" ) self.no_context_takeover = no_context_takeover @@ -274,12 +263,7 @@ def __repr__(self): :rtype: str """ return ( - "PerMessageBrotliAccept(offer = %s, request_no_context_takeover = %s, no_context_takeover = %s)" - % ( - self.offer.__repr__(), - self.request_no_context_takeover, - self.no_context_takeover, - ) + f"PerMessageBrotliAccept(offer = {self.offer.__repr__()}, request_no_context_takeover = {self.request_no_context_takeover}, no_context_takeover = {self.no_context_takeover})" ) @@ -305,8 +289,7 @@ def parse(cls, params): for p in params: if len(params[p]) > 1: raise Exception( - "multiple occurrence of extension parameter '%s' for extension '%s'" - % (p, cls.EXTENSION_NAME) + f"multiple occurrence of extension parameter '{p}' for extension '{cls.EXTENSION_NAME}'" ) val = params[p][0] @@ -315,8 +298,7 @@ def parse(cls, params): # noinspection PySimplifyBooleanCheck if val is not True: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: client_no_context_takeover = True @@ -325,16 +307,14 @@ def parse(cls, params): # noinspection PySimplifyBooleanCheck if val is not True: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: server_no_context_takeover = True else: raise Exception( - "illegal extension parameter '%s' for extension '%s'" - % (p, cls.EXTENSION_NAME) + f"illegal extension parameter '{p}' for extension '{cls.EXTENSION_NAME}'" ) response = cls(client_no_context_takeover, server_no_context_takeover) @@ -365,8 +345,7 @@ def __repr__(self): :rtype: str """ return ( - "PerMessageBrotliResponse(client_no_context_takeover = %s, server_no_context_takeover = %s)" - % (self.client_no_context_takeover, self.server_no_context_takeover) + f"PerMessageBrotliResponse(client_no_context_takeover = {self.client_no_context_takeover}, server_no_context_takeover = {self.server_no_context_takeover})" ) @@ -387,21 +366,19 @@ def __init__(self, response, no_context_takeover=None): :type no_context_takeover: bool """ if not isinstance(response, PerMessageBrotliResponse): - raise Exception("invalid type %s for response" % type(response)) + raise Exception(f"invalid type {type(response)} for response") self.response = response if no_context_takeover is not None: if type(no_context_takeover) != bool: raise Exception( - "invalid type %s for no_context_takeover" - % type(no_context_takeover) + f"invalid type {type(no_context_takeover)} for no_context_takeover" ) if response.client_no_context_takeover and not no_context_takeover: raise Exception( - "invalid value %s for no_context_takeover - server requested feature" - % no_context_takeover + f"invalid value {no_context_takeover} for no_context_takeover - server requested feature" ) self.no_context_takeover = no_context_takeover @@ -427,8 +404,7 @@ def __repr__(self): :rtype: str """ return ( - "PerMessageBrotliResponseAccept(response = %s, no_context_takeover = %s)" - % (self.response.__repr__(), self.no_context_takeover) + f"PerMessageBrotliResponseAccept(response = {self.response.__repr__()}, no_context_takeover = {self.no_context_takeover})" ) @@ -482,12 +458,7 @@ def __json__(self): def __repr__(self): return ( - "PerMessageBrotli(is_server = %s, server_no_context_takeover = %s, client_no_context_takeover = %s)" - % ( - self._is_server, - self.server_no_context_takeover, - self.client_no_context_takeover, - ) + f"PerMessageBrotli(is_server = {self._is_server}, server_no_context_takeover = {self.server_no_context_takeover}, client_no_context_takeover = {self.client_no_context_takeover})" ) def start_compress_message(self): diff --git a/src/autobahn/websocket/compress_bzip2.py b/src/autobahn/websocket/compress_bzip2.py index f4c8a3f6a..9b1050383 100644 --- a/src/autobahn/websocket/compress_bzip2.py +++ b/src/autobahn/websocket/compress_bzip2.py @@ -44,7 +44,7 @@ ) -class PerMessageBzip2Mixin(object): +class PerMessageBzip2Mixin: """ Mixin class for this extension. """ @@ -84,8 +84,7 @@ def parse(cls, params): for p in params: if len(params[p]) > 1: raise Exception( - "multiple occurrence of extension parameter '%s' for extension '%s'" - % (p, cls.EXTENSION_NAME) + f"multiple occurrence of extension parameter '{p}' for extension '{cls.EXTENSION_NAME}'" ) val = params[p][0] @@ -94,8 +93,7 @@ def parse(cls, params): # noinspection PySimplifyBooleanCheck if val is not True: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: accept_max_compress_level = True @@ -105,21 +103,18 @@ def parse(cls, params): val = int(val) except: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) if val not in PerMessageBzip2Mixin.COMPRESS_LEVEL_PERMISSIBLE_VALUES: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: request_max_compress_level = val else: raise Exception( - "illegal extension parameter '%s' for extension '%s'" - % (p, cls.EXTENSION_NAME) + f"illegal extension parameter '{p}' for extension '{cls.EXTENSION_NAME}'" ) offer = cls(accept_max_compress_level, request_max_compress_level) @@ -136,8 +131,7 @@ def __init__(self, accept_max_compress_level=True, request_max_compress_level=0) """ if type(accept_max_compress_level) != bool: raise Exception( - "invalid type %s for accept_max_compress_level" - % type(accept_max_compress_level) + f"invalid type {type(accept_max_compress_level)} for accept_max_compress_level" ) self.accept_max_compress_level = accept_max_compress_level @@ -147,8 +141,7 @@ def __init__(self, accept_max_compress_level=True, request_max_compress_level=0) and request_max_compress_level not in self.COMPRESS_LEVEL_PERMISSIBLE_VALUES ): raise Exception( - "invalid value %s for request_max_compress_level - permissible values %s" - % (request_max_compress_level, self.COMPRESS_LEVEL_PERMISSIBLE_VALUES) + f"invalid value {request_max_compress_level} for request_max_compress_level - permissible values {self.COMPRESS_LEVEL_PERMISSIBLE_VALUES}" ) self.request_max_compress_level = request_max_compress_level @@ -165,7 +158,7 @@ def get_extension_string(self): pmce_string += "; client_max_compress_level" if self.request_max_compress_level != 0: pmce_string += ( - "; server_max_compress_level=%d" % self.request_max_compress_level + f"; server_max_compress_level={self.request_max_compress_level}" ) return pmce_string @@ -190,8 +183,7 @@ def __repr__(self): :rtype: str """ return ( - "PerMessageBzip2Offer(accept_max_compress_level = %s, request_max_compress_level = %s)" - % (self.accept_max_compress_level, self.request_max_compress_level) + f"PerMessageBzip2Offer(accept_max_compress_level = {self.accept_max_compress_level}, request_max_compress_level = {self.request_max_compress_level})" ) @@ -213,7 +205,7 @@ def __init__(self, offer, request_max_compress_level=0, compress_level=None): :type compress_level: int """ if not isinstance(offer, PerMessageBzip2Offer): - raise Exception("invalid type %s for offer" % type(offer)) + raise Exception(f"invalid type {type(offer)} for offer") self.offer = offer @@ -222,14 +214,12 @@ def __init__(self, offer, request_max_compress_level=0, compress_level=None): and request_max_compress_level not in self.COMPRESS_LEVEL_PERMISSIBLE_VALUES ): raise Exception( - "invalid value %s for request_max_compress_level - permissible values %s" - % (request_max_compress_level, self.COMPRESS_LEVEL_PERMISSIBLE_VALUES) + f"invalid value {request_max_compress_level} for request_max_compress_level - permissible values {self.COMPRESS_LEVEL_PERMISSIBLE_VALUES}" ) if request_max_compress_level != 0 and not offer.accept_max_compress_level: raise Exception( - "invalid value %s for request_max_compress_level - feature unsupported by client" - % request_max_compress_level + f"invalid value {request_max_compress_level} for request_max_compress_level - feature unsupported by client" ) self.request_max_compress_level = request_max_compress_level @@ -237,8 +227,7 @@ def __init__(self, offer, request_max_compress_level=0, compress_level=None): if compress_level is not None: if compress_level not in self.COMPRESS_LEVEL_PERMISSIBLE_VALUES: raise Exception( - "invalid value %s for compress_level - permissible values %s" - % (compress_level, self.COMPRESS_LEVEL_PERMISSIBLE_VALUES) + f"invalid value {compress_level} for compress_level - permissible values {self.COMPRESS_LEVEL_PERMISSIBLE_VALUES}" ) if ( @@ -246,8 +235,7 @@ def __init__(self, offer, request_max_compress_level=0, compress_level=None): and compress_level > offer.request_max_compress_level ): raise Exception( - "invalid value %s for compress_level - client requested lower maximum value" - % compress_level + f"invalid value {compress_level} for compress_level - client requested lower maximum value" ) self.compress_level = compress_level @@ -262,11 +250,11 @@ def get_extension_string(self): pmce_string = self.EXTENSION_NAME if self.offer.request_max_compress_level != 0: pmce_string += ( - "; server_max_compress_level=%d" % self.offer.request_max_compress_level + f"; server_max_compress_level={self.offer.request_max_compress_level}" ) if self.request_max_compress_level != 0: pmce_string += ( - "; client_max_compress_level=%d" % self.request_max_compress_level + f"; client_max_compress_level={self.request_max_compress_level}" ) return pmce_string @@ -292,12 +280,7 @@ def __repr__(self): :rtype: str """ return ( - "PerMessageBzip2Accept(offer = %s, request_max_compress_level = %s, compress_level = %s)" - % ( - self.offer.__repr__(), - self.request_max_compress_level, - self.compress_level, - ) + f"PerMessageBzip2Accept(offer = {self.offer.__repr__()}, request_max_compress_level = {self.request_max_compress_level}, compress_level = {self.compress_level})" ) @@ -323,8 +306,7 @@ def parse(cls, params): for p in params: if len(params[p]) > 1: raise Exception( - "multiple occurrence of extension parameter '%s' for extension '%s'" - % (p, cls.EXTENSION_NAME) + f"multiple occurrence of extension parameter '{p}' for extension '{cls.EXTENSION_NAME}'" ) val = params[p][0] @@ -334,13 +316,11 @@ def parse(cls, params): val = int(val) except: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) if val not in PerMessageBzip2Mixin.COMPRESS_LEVEL_PERMISSIBLE_VALUES: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: client_max_compress_level = val @@ -350,21 +330,18 @@ def parse(cls, params): val = int(val) except: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) if val not in PerMessageBzip2Mixin.COMPRESS_LEVEL_PERMISSIBLE_VALUES: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: server_max_compress_level = val else: raise Exception( - "illegal extension parameter '%s' for extension '%s'" - % (p, cls.EXTENSION_NAME) + f"illegal extension parameter '{p}' for extension '{cls.EXTENSION_NAME}'" ) response = cls(client_max_compress_level, server_max_compress_level) @@ -395,8 +372,7 @@ def __repr__(self): :rtype: str """ return ( - "PerMessageBzip2Response(client_max_compress_level = %s, server_max_compress_level = %s)" - % (self.client_max_compress_level, self.server_max_compress_level) + f"PerMessageBzip2Response(client_max_compress_level = {self.client_max_compress_level}, server_max_compress_level = {self.server_max_compress_level})" ) @@ -417,15 +393,14 @@ def __init__(self, response, compress_level=None): :type compress_level: int """ if not isinstance(response, PerMessageBzip2Response): - raise Exception("invalid type %s for response" % type(response)) + raise Exception(f"invalid type {type(response)} for response") self.response = response if compress_level is not None: if compress_level not in self.COMPRESS_LEVEL_PERMISSIBLE_VALUES: raise Exception( - "invalid value %s for compress_level - permissible values %s" - % (compress_level, self.COMPRESS_LEVEL_PERMISSIBLE_VALUES) + f"invalid value {compress_level} for compress_level - permissible values {self.COMPRESS_LEVEL_PERMISSIBLE_VALUES}" ) if ( @@ -433,8 +408,7 @@ def __init__(self, response, compress_level=None): and compress_level > response.client_max_compress_level ): raise Exception( - "invalid value %s for compress_level - server requested lower maximum value" - % compress_level + f"invalid value {compress_level} for compress_level - server requested lower maximum value" ) self.compress_level = compress_level @@ -459,10 +433,7 @@ def __repr__(self): :returns: Python string representation. :rtype: str """ - return "PerMessageBzip2ResponseAccept(response = %s, compress_level = %s)" % ( - self.response.__repr__(), - self.compress_level, - ) + return f"PerMessageBzip2ResponseAccept(response = {self.response.__repr__()}, compress_level = {self.compress_level})" class PerMessageBzip2(PerMessageCompress, PerMessageBzip2Mixin): @@ -524,12 +495,7 @@ def __json__(self): def __repr__(self): return ( - "PerMessageBzip2(isServer = %s, server_max_compress_level = %s, client_max_compress_level = %s)" - % ( - self._isServer, - self.server_max_compress_level, - self.client_max_compress_level, - ) + f"PerMessageBzip2(isServer = {self._isServer}, server_max_compress_level = {self.server_max_compress_level}, client_max_compress_level = {self.client_max_compress_level})" ) def start_compress_message(self): diff --git a/src/autobahn/websocket/compress_deflate.py b/src/autobahn/websocket/compress_deflate.py index 86e253291..638efaaa8 100644 --- a/src/autobahn/websocket/compress_deflate.py +++ b/src/autobahn/websocket/compress_deflate.py @@ -45,7 +45,7 @@ ) -class PerMessageDeflateMixin(object): +class PerMessageDeflateMixin: """ Mixin class for this extension. """ @@ -98,8 +98,7 @@ def parse(cls, params): for p in params: if len(params[p]) > 1: raise Exception( - "multiple occurrence of extension parameter '%s' for extension '%s'" - % (p, cls.EXTENSION_NAME) + f"multiple occurrence of extension parameter '{p}' for extension '{cls.EXTENSION_NAME}'" ) val = params[p][0] @@ -118,8 +117,7 @@ def parse(cls, params): val = int(val) except: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: if ( @@ -127,8 +125,7 @@ def parse(cls, params): not in PerMessageDeflateMixin.WINDOW_SIZE_PERMISSIBLE_VALUES ): raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: # FIXME (maybe): possibly forward/process the client hint! @@ -141,8 +138,7 @@ def parse(cls, params): # noinspection PySimplifyBooleanCheck if val is not True: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: accept_no_context_takeover = True @@ -152,14 +148,12 @@ def parse(cls, params): val = int(val) except: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: if val not in PerMessageDeflateMixin.WINDOW_SIZE_PERMISSIBLE_VALUES: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: request_max_window_bits = val @@ -168,16 +162,14 @@ def parse(cls, params): # noinspection PySimplifyBooleanCheck if val is not True: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: request_no_context_takeover = True else: raise Exception( - "illegal extension parameter '%s' for extension '%s'" - % (p, cls.EXTENSION_NAME) + f"illegal extension parameter '{p}' for extension '{cls.EXTENSION_NAME}'" ) offer = cls( @@ -209,24 +201,21 @@ def __init__( """ if type(accept_no_context_takeover) != bool: raise Exception( - "invalid type %s for accept_no_context_takeover" - % type(accept_no_context_takeover) + f"invalid type {type(accept_no_context_takeover)} for accept_no_context_takeover" ) self.accept_no_context_takeover = accept_no_context_takeover if type(accept_max_window_bits) != bool: raise Exception( - "invalid type %s for accept_max_window_bits" - % type(accept_max_window_bits) + f"invalid type {type(accept_max_window_bits)} for accept_max_window_bits" ) self.accept_max_window_bits = accept_max_window_bits if type(request_no_context_takeover) != bool: raise Exception( - "invalid type %s for request_no_context_takeover" - % type(request_no_context_takeover) + f"invalid type {type(request_no_context_takeover)} for request_no_context_takeover" ) self.request_no_context_takeover = request_no_context_takeover @@ -236,8 +225,7 @@ def __init__( and request_max_window_bits not in self.WINDOW_SIZE_PERMISSIBLE_VALUES ): raise Exception( - "invalid value %s for request_max_window_bits - permissible values %s" - % (request_max_window_bits, self.WINDOW_SIZE_PERMISSIBLE_VALUES) + f"invalid value {request_max_window_bits} for request_max_window_bits - permissible values {self.WINDOW_SIZE_PERMISSIBLE_VALUES}" ) self.request_max_window_bits = request_max_window_bits @@ -257,7 +245,7 @@ def get_extension_string(self): if self.request_no_context_takeover: pmce_string += "; server_no_context_takeover" if self.request_max_window_bits != 0: - pmce_string += "; server_max_window_bits=%d" % self.request_max_window_bits + pmce_string += f"; server_max_window_bits={self.request_max_window_bits}" return pmce_string def __json__(self): @@ -283,13 +271,7 @@ def __repr__(self): :rtype: str """ return ( - "PerMessageDeflateOffer(accept_no_context_takeover = %s, accept_max_window_bits = %s, request_no_context_takeover = %s, request_max_window_bits = %s)" - % ( - self.accept_no_context_takeover, - self.accept_max_window_bits, - self.request_no_context_takeover, - self.request_max_window_bits, - ) + f"PerMessageDeflateOffer(accept_no_context_takeover = {self.accept_no_context_takeover}, accept_max_window_bits = {self.accept_max_window_bits}, request_no_context_takeover = {self.request_no_context_takeover}, request_max_window_bits = {self.request_max_window_bits})" ) @@ -331,20 +313,18 @@ def __init__( :type mem_level: int """ if not isinstance(offer, PerMessageDeflateOffer): - raise Exception("invalid type %s for offer" % type(offer)) + raise Exception(f"invalid type {type(offer)} for offer") self.offer = offer if type(request_no_context_takeover) != bool: raise Exception( - "invalid type %s for request_no_context_takeover" - % type(request_no_context_takeover) + f"invalid type {type(request_no_context_takeover)} for request_no_context_takeover" ) if request_no_context_takeover and not offer.accept_no_context_takeover: raise Exception( - "invalid value %s for request_no_context_takeover - feature unsupported by client" - % request_no_context_takeover + f"invalid value {request_no_context_takeover} for request_no_context_takeover - feature unsupported by client" ) self.request_no_context_takeover = request_no_context_takeover @@ -354,14 +334,12 @@ def __init__( and request_max_window_bits not in self.WINDOW_SIZE_PERMISSIBLE_VALUES ): raise Exception( - "invalid value %s for request_max_window_bits - permissible values %s" - % (request_max_window_bits, self.WINDOW_SIZE_PERMISSIBLE_VALUES) + f"invalid value {request_max_window_bits} for request_max_window_bits - permissible values {self.WINDOW_SIZE_PERMISSIBLE_VALUES}" ) if request_max_window_bits != 0 and not offer.accept_max_window_bits: raise Exception( - "invalid value %s for request_max_window_bits - feature unsupported by client" - % request_max_window_bits + f"invalid value {request_max_window_bits} for request_max_window_bits - feature unsupported by client" ) self.request_max_window_bits = request_max_window_bits @@ -369,14 +347,12 @@ def __init__( if no_context_takeover is not None: if type(no_context_takeover) != bool: raise Exception( - "invalid type %s for no_context_takeover" - % type(no_context_takeover) + f"invalid type {type(no_context_takeover)} for no_context_takeover" ) if offer.request_no_context_takeover and not no_context_takeover: raise Exception( - "invalid value %s for no_context_takeover - client requested feature" - % no_context_takeover + f"invalid value {no_context_takeover} for no_context_takeover - client requested feature" ) self.no_context_takeover = no_context_takeover @@ -384,8 +360,7 @@ def __init__( if window_bits is not None: if window_bits not in self.WINDOW_SIZE_PERMISSIBLE_VALUES: raise Exception( - "invalid value %s for window_bits - permissible values %s" - % (window_bits, self.WINDOW_SIZE_PERMISSIBLE_VALUES) + f"invalid value {window_bits} for window_bits - permissible values {self.WINDOW_SIZE_PERMISSIBLE_VALUES}" ) if ( @@ -393,8 +368,7 @@ def __init__( and window_bits > offer.request_max_window_bits ): raise Exception( - "invalid value %s for window_bits - client requested lower maximum value" - % window_bits + f"invalid value {window_bits} for window_bits - client requested lower maximum value" ) self.window_bits = window_bits @@ -402,8 +376,7 @@ def __init__( if mem_level is not None: if mem_level not in self.MEM_LEVEL_PERMISSIBLE_VALUES: raise Exception( - "invalid value %s for mem_level - permissible values %s" - % (mem_level, self.MEM_LEVEL_PERMISSIBLE_VALUES) + f"invalid value {mem_level} for mem_level - permissible values {self.MEM_LEVEL_PERMISSIBLE_VALUES}" ) self.mem_level = mem_level @@ -421,12 +394,12 @@ def get_extension_string(self): pmce_string += "; server_no_context_takeover" if self.offer.request_max_window_bits != 0: pmce_string += ( - "; server_max_window_bits=%d" % self.offer.request_max_window_bits + f"; server_max_window_bits={self.offer.request_max_window_bits}" ) if self.request_no_context_takeover: pmce_string += "; client_no_context_takeover" if self.request_max_window_bits != 0: - pmce_string += "; client_max_window_bits=%d" % self.request_max_window_bits + pmce_string += f"; client_max_window_bits={self.request_max_window_bits}" return pmce_string def __json__(self): @@ -455,16 +428,7 @@ def __repr__(self): :rtype: str """ return ( - "PerMessageDeflateOfferAccept(offer = %s, request_no_context_takeover = %s, request_max_window_bits = %s, no_context_takeover = %s, window_bits = %s, mem_level = %s, max_message_size = %s)" - % ( - self.offer.__repr__(), - self.request_no_context_takeover, - self.request_max_window_bits, - self.no_context_takeover, - self.window_bits, - self.mem_level, - self.max_message_size, - ) + f"PerMessageDeflateOfferAccept(offer = {self.offer.__repr__()}, request_no_context_takeover = {self.request_no_context_takeover}, request_max_window_bits = {self.request_max_window_bits}, no_context_takeover = {self.no_context_takeover}, window_bits = {self.window_bits}, mem_level = {self.mem_level}, max_message_size = {self.max_message_size})" ) @@ -493,8 +457,7 @@ def parse(cls, params): for p in params: if len(params[p]) > 1: raise Exception( - "multiple occurrence of extension parameter '%s' for extension '%s'" - % (p, cls.EXTENSION_NAME) + f"multiple occurrence of extension parameter '{p}' for extension '{cls.EXTENSION_NAME}'" ) val = params[p][0] @@ -504,14 +467,12 @@ def parse(cls, params): val = int(val) except: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: if val not in PerMessageDeflateMixin.WINDOW_SIZE_PERMISSIBLE_VALUES: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: client_max_window_bits = val @@ -520,8 +481,7 @@ def parse(cls, params): # noinspection PySimplifyBooleanCheck if val is not True: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: client_no_context_takeover = True @@ -531,14 +491,12 @@ def parse(cls, params): val = int(val) except: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: if val not in PerMessageDeflateMixin.WINDOW_SIZE_PERMISSIBLE_VALUES: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: server_max_window_bits = val @@ -547,16 +505,14 @@ def parse(cls, params): # noinspection PySimplifyBooleanCheck if val is not True: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: server_no_context_takeover = True else: raise Exception( - "illegal extension parameter '%s' for extension '%s'" - % (p, cls.EXTENSION_NAME) + f"illegal extension parameter '{p}' for extension '{cls.EXTENSION_NAME}'" ) response = cls( @@ -613,13 +569,7 @@ def __repr__(self): :rtype: str """ return ( - "PerMessageDeflateResponse(client_max_window_bits = %s, client_no_context_takeover = %s, server_max_window_bits = %s, server_no_context_takeover = %s)" - % ( - self.client_max_window_bits, - self.client_no_context_takeover, - self.server_max_window_bits, - self.server_no_context_takeover, - ) + f"PerMessageDeflateResponse(client_max_window_bits = {self.client_max_window_bits}, client_no_context_takeover = {self.client_no_context_takeover}, server_max_window_bits = {self.server_max_window_bits}, server_no_context_takeover = {self.server_no_context_takeover})" ) @@ -652,21 +602,19 @@ def __init__( :type mem_level: int """ if not isinstance(response, PerMessageDeflateResponse): - raise Exception("invalid type %s for response" % type(response)) + raise Exception(f"invalid type {type(response)} for response") self.response = response if no_context_takeover is not None: if type(no_context_takeover) != bool: raise Exception( - "invalid type %s for no_context_takeover" - % type(no_context_takeover) + f"invalid type {type(no_context_takeover)} for no_context_takeover" ) if response.client_no_context_takeover and not no_context_takeover: raise Exception( - "invalid value %s for no_context_takeover - server requested feature" - % no_context_takeover + f"invalid value {no_context_takeover} for no_context_takeover - server requested feature" ) self.no_context_takeover = no_context_takeover @@ -674,8 +622,7 @@ def __init__( if window_bits is not None: if window_bits not in self.WINDOW_SIZE_PERMISSIBLE_VALUES: raise Exception( - "invalid value %s for window_bits - permissible values %s" - % (window_bits, self.WINDOW_SIZE_PERMISSIBLE_VALUES) + f"invalid value {window_bits} for window_bits - permissible values {self.WINDOW_SIZE_PERMISSIBLE_VALUES}" ) if ( @@ -683,8 +630,7 @@ def __init__( and window_bits > response.client_max_window_bits ): raise Exception( - "invalid value %s for window_bits - server requested lower maximum value" - % window_bits + f"invalid value {window_bits} for window_bits - server requested lower maximum value" ) self.window_bits = window_bits @@ -692,8 +638,7 @@ def __init__( if mem_level is not None: if mem_level not in self.MEM_LEVEL_PERMISSIBLE_VALUES: raise Exception( - "invalid value %s for mem_level - permissible values %s" - % (mem_level, self.MEM_LEVEL_PERMISSIBLE_VALUES) + f"invalid value {mem_level} for mem_level - permissible values {self.MEM_LEVEL_PERMISSIBLE_VALUES}" ) self.mem_level = mem_level @@ -722,13 +667,7 @@ def __repr__(self): :rtype: str """ return ( - "PerMessageDeflateResponseAccept(response = %s, no_context_takeover = %s, window_bits = %s, mem_level = %s)" - % ( - self.response.__repr__(), - self.no_context_takeover, - self.window_bits, - self.mem_level, - ) + f"PerMessageDeflateResponseAccept(response = {self.response.__repr__()}, no_context_takeover = {self.no_context_takeover}, window_bits = {self.window_bits}, mem_level = {self.mem_level})" ) @@ -830,15 +769,7 @@ def __json__(self): def __repr__(self): return ( - "PerMessageDeflate(is_server = %s, server_no_context_takeover = %s, client_no_context_takeover = %s, server_max_window_bits = %s, client_max_window_bits = %s, mem_level = %s)" - % ( - self._is_server, - self.server_no_context_takeover, - self.client_no_context_takeover, - self.server_max_window_bits, - self.client_max_window_bits, - self.mem_level, - ) + f"PerMessageDeflate(is_server = {self._is_server}, server_no_context_takeover = {self.server_no_context_takeover}, client_no_context_takeover = {self.client_no_context_takeover}, server_max_window_bits = {self.server_max_window_bits}, client_max_window_bits = {self.client_max_window_bits}, mem_level = {self.mem_level})" ) def start_compress_message(self): diff --git a/src/autobahn/websocket/compress_snappy.py b/src/autobahn/websocket/compress_snappy.py index 4fda43810..e8337e4c7 100644 --- a/src/autobahn/websocket/compress_snappy.py +++ b/src/autobahn/websocket/compress_snappy.py @@ -44,7 +44,7 @@ ) -class PerMessageSnappyMixin(object): +class PerMessageSnappyMixin: """ Mixin class for this extension. """ @@ -80,8 +80,7 @@ def parse(cls, params): for p in params: if len(params[p]) > 1: raise Exception( - "multiple occurrence of extension parameter '%s' for extension '%s'" - % (p, cls.EXTENSION_NAME) + f"multiple occurrence of extension parameter '{p}' for extension '{cls.EXTENSION_NAME}'" ) val = params[p][0] @@ -90,8 +89,7 @@ def parse(cls, params): # noinspection PySimplifyBooleanCheck if val is not True: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: accept_no_context_takeover = True @@ -100,16 +98,14 @@ def parse(cls, params): # noinspection PySimplifyBooleanCheck if val is not True: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: request_no_context_takeover = True else: raise Exception( - "illegal extension parameter '%s' for extension '%s'" - % (p, cls.EXTENSION_NAME) + f"illegal extension parameter '{p}' for extension '{cls.EXTENSION_NAME}'" ) offer = cls(accept_no_context_takeover, request_no_context_takeover) @@ -127,16 +123,14 @@ def __init__( """ if type(accept_no_context_takeover) != bool: raise Exception( - "invalid type %s for accept_no_context_takeover" - % type(accept_no_context_takeover) + f"invalid type {type(accept_no_context_takeover)} for accept_no_context_takeover" ) self.accept_no_context_takeover = accept_no_context_takeover if type(request_no_context_takeover) != bool: raise Exception( - "invalid type %s for request_no_context_takeover" - % type(request_no_context_takeover) + f"invalid type {type(request_no_context_takeover)} for request_no_context_takeover" ) self.request_no_context_takeover = request_no_context_takeover @@ -176,8 +170,7 @@ def __repr__(self): :rtype: str """ return ( - "PerMessageSnappyOffer(accept_no_context_takeover = %s, request_no_context_takeover = %s)" - % (self.accept_no_context_takeover, self.request_no_context_takeover) + f"PerMessageSnappyOffer(accept_no_context_takeover = {self.accept_no_context_takeover}, request_no_context_takeover = {self.request_no_context_takeover})" ) @@ -200,20 +193,18 @@ def __init__( :type no_context_takeover: bool """ if not isinstance(offer, PerMessageSnappyOffer): - raise Exception("invalid type %s for offer" % type(offer)) + raise Exception(f"invalid type {type(offer)} for offer") self.offer = offer if type(request_no_context_takeover) != bool: raise Exception( - "invalid type %s for request_no_context_takeover" - % type(request_no_context_takeover) + f"invalid type {type(request_no_context_takeover)} for request_no_context_takeover" ) if request_no_context_takeover and not offer.accept_no_context_takeover: raise Exception( - "invalid value %s for request_no_context_takeover - feature unsupported by client" - % request_no_context_takeover + f"invalid value {request_no_context_takeover} for request_no_context_takeover - feature unsupported by client" ) self.request_no_context_takeover = request_no_context_takeover @@ -221,14 +212,12 @@ def __init__( if no_context_takeover is not None: if type(no_context_takeover) != bool: raise Exception( - "invalid type %s for no_context_takeover" - % type(no_context_takeover) + f"invalid type {type(no_context_takeover)} for no_context_takeover" ) if offer.request_no_context_takeover and not no_context_takeover: raise Exception( - "invalid value %s for no_context_takeover - client requested feature" - % no_context_takeover + f"invalid value {no_context_takeover} for no_context_takeover - client requested feature" ) self.no_context_takeover = no_context_takeover @@ -269,12 +258,7 @@ def __repr__(self): :rtype: str """ return ( - "PerMessageSnappyAccept(offer = %s, request_no_context_takeover = %s, no_context_takeover = %s)" - % ( - self.offer.__repr__(), - self.request_no_context_takeover, - self.no_context_takeover, - ) + f"PerMessageSnappyAccept(offer = {self.offer.__repr__()}, request_no_context_takeover = {self.request_no_context_takeover}, no_context_takeover = {self.no_context_takeover})" ) @@ -300,8 +284,7 @@ def parse(cls, params): for p in params: if len(params[p]) > 1: raise Exception( - "multiple occurrence of extension parameter '%s' for extension '%s'" - % (p, cls.EXTENSION_NAME) + f"multiple occurrence of extension parameter '{p}' for extension '{cls.EXTENSION_NAME}'" ) val = params[p][0] @@ -310,8 +293,7 @@ def parse(cls, params): # noinspection PySimplifyBooleanCheck if val is not True: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: client_no_context_takeover = True @@ -320,16 +302,14 @@ def parse(cls, params): # noinspection PySimplifyBooleanCheck if val is not True: raise Exception( - "illegal extension parameter value '%s' for parameter '%s' of extension '%s'" - % (val, p, cls.EXTENSION_NAME) + f"illegal extension parameter value '{val}' for parameter '{p}' of extension '{cls.EXTENSION_NAME}'" ) else: server_no_context_takeover = True else: raise Exception( - "illegal extension parameter '%s' for extension '%s'" - % (p, cls.EXTENSION_NAME) + f"illegal extension parameter '{p}' for extension '{cls.EXTENSION_NAME}'" ) response = cls(client_no_context_takeover, server_no_context_takeover) @@ -360,8 +340,7 @@ def __repr__(self): :rtype: str """ return ( - "PerMessageSnappyResponse(client_no_context_takeover = %s, server_no_context_takeover = %s)" - % (self.client_no_context_takeover, self.server_no_context_takeover) + f"PerMessageSnappyResponse(client_no_context_takeover = {self.client_no_context_takeover}, server_no_context_takeover = {self.server_no_context_takeover})" ) @@ -382,21 +361,19 @@ def __init__(self, response, no_context_takeover=None): :type no_context_takeover: bool """ if not isinstance(response, PerMessageSnappyResponse): - raise Exception("invalid type %s for response" % type(response)) + raise Exception(f"invalid type {type(response)} for response") self.response = response if no_context_takeover is not None: if type(no_context_takeover) != bool: raise Exception( - "invalid type %s for no_context_takeover" - % type(no_context_takeover) + f"invalid type {type(no_context_takeover)} for no_context_takeover" ) if response.client_no_context_takeover and not no_context_takeover: raise Exception( - "invalid value %s for no_context_takeover - server requested feature" - % no_context_takeover + f"invalid value {no_context_takeover} for no_context_takeover - server requested feature" ) self.no_context_takeover = no_context_takeover @@ -422,8 +399,7 @@ def __repr__(self): :rtype: str """ return ( - "PerMessageSnappyResponseAccept(response = %s, no_context_takeover = %s)" - % (self.response.__repr__(), self.no_context_takeover) + f"PerMessageSnappyResponseAccept(response = {self.response.__repr__()}, no_context_takeover = {self.no_context_takeover})" ) @@ -477,12 +453,7 @@ def __json__(self): def __repr__(self): return ( - "PerMessageSnappy(is_server = %s, server_no_context_takeover = %s, client_no_context_takeover = %s)" - % ( - self._is_server, - self.server_no_context_takeover, - self.client_no_context_takeover, - ) + f"PerMessageSnappy(is_server = {self._is_server}, server_no_context_takeover = {self.server_no_context_takeover}, client_no_context_takeover = {self.client_no_context_takeover})" ) def start_compress_message(self): diff --git a/src/autobahn/websocket/interfaces.py b/src/autobahn/websocket/interfaces.py index 1728eec64..eca98713f 100644 --- a/src/autobahn/websocket/interfaces.py +++ b/src/autobahn/websocket/interfaces.py @@ -25,7 +25,6 @@ ############################################################################### import abc -from typing import Dict, Optional, Tuple, Union from autobahn.util import public from autobahn.wamp.types import TransportDetails @@ -481,7 +480,7 @@ class IWebSocketChannel(abc.ABC): @abc.abstractmethod def onConnecting( self, transport_details: TransportDetails - ) -> Optional[ConnectingRequest]: + ) -> ConnectingRequest | None: """ This method is called when the WebSocket peer is connected at the byte stream level (e.g. TCP, TLS or Serial), but before the WebSocket opening handshake (e.g. at the HTTP request level). @@ -497,8 +496,8 @@ def onConnecting( @public @abc.abstractmethod def onConnect( - self, request_or_response: Union[ConnectionRequest, ConnectionResponse] - ) -> Union[Optional[str], Tuple[Optional[str], Dict[str, str]]]: + self, request_or_response: ConnectionRequest | ConnectionResponse + ) -> str | None | tuple[str | None, dict[str, str]]: """ Callback fired during WebSocket opening handshake when a client connects to a server with request with a :class:`ConnectionRequest` from the client or when a server connection was established @@ -555,7 +554,7 @@ def onMessage(self, payload: bytes, isBinary: bool): @public @abc.abstractmethod - def sendClose(self, code: Optional[int] = None, reason: Optional[str] = None): + def sendClose(self, code: int | None = None, reason: str | None = None): """ Starts a WebSocket closing handshake tearing down the WebSocket connection. @@ -580,7 +579,7 @@ def onClose(self, wasClean: bool, code: int, reason: str): """ @abc.abstractmethod - def sendPing(self, payload: Optional[bytes] = None): + def sendPing(self, payload: bytes | None = None): """ Send a WebSocket ping to the peer. @@ -600,7 +599,7 @@ def onPing(self, payload: bytes): """ @abc.abstractmethod - def sendPong(self, payload: Optional[bytes] = None): + def sendPong(self, payload: bytes | None = None): """ Send a WebSocket pong to the peer. diff --git a/src/autobahn/websocket/protocol.py b/src/autobahn/websocket/protocol.py index 638a10575..e1e14a397 100755 --- a/src/autobahn/websocket/protocol.py +++ b/src/autobahn/websocket/protocol.py @@ -38,7 +38,8 @@ import time from collections import deque from pprint import pformat -from typing import Literal, Iterator, overload +from typing import Literal, overload +from collections.abc import Iterator from urllib import parse import hyperlink @@ -113,7 +114,7 @@ def _url_to_origin(url): port = None if not host: - raise ValueError("No host part in Origin '{}'".format(url)) + raise ValueError(f"No host part in Origin '{url}'") return scheme, host, port @@ -165,7 +166,7 @@ def _is_same_origin(websocket_origin, host_scheme, host_port, host_policy): return False -class TrafficStats(object): +class TrafficStats: def __init__(self): self.reset() @@ -244,7 +245,7 @@ def __str__(self): return json.dumps(self.__json__()) -class FrameHeader(object): +class FrameHeader: """ Thin-wrapper for storing WebSocket frame metadata. @@ -301,7 +302,7 @@ def parseHttpHeader(data: bytes) -> tuple[str, dict[str, str], dict[str, int]]: # handle HTTP headers split across multiple lines if key in http_headers: - http_headers[key] += ", {}".format(value) + http_headers[key] += f", {value}" http_headers_cnt[key] += 1 else: http_headers[key] = value @@ -312,7 +313,7 @@ def parseHttpHeader(data: bytes) -> tuple[str, dict[str, str], dict[str, int]]: return http_status_line, http_headers, http_headers_cnt -class Timings(object): +class Timings: """ Helper class to track timings by key. This class also supports item access, iteration and conversion to string. @@ -352,13 +353,13 @@ def diff(self, startKey: str, endKey: str, formatted: bool=True) -> str | float d = self._timings[endKey] - self._timings[startKey] if formatted: if d < 0.00001: # 10us - s = "{} ns".format(round(d * 1000000000.0)) + s = f"{round(d * 1000000000.0)} ns" elif d < 0.01: # 10ms - s = "{} us".format(round(d * 1000000.0)) + s = f"{round(d * 1000000.0)} us" elif d < 10: # 10s - s = "{} ms".format(round(d * 1000.0)) + s = f"{round(d * 1000.0)} ms" else: - s = "{} s".format(round(d)) + s = f"{round(d)} s" return s.rjust(8) else: return d @@ -637,18 +638,14 @@ def onMessageFrameBegin(self, length: int) -> None: self._max_message_size_exceeded( self.message_data_total_length, self.maxMessagePayloadSize, - "received WebSocket message size {} exceeds payload limit of {} octets".format( - self.message_data_total_length, self.maxMessagePayloadSize - ), + f"received WebSocket message size {self.message_data_total_length} exceeds payload limit of {self.maxMessagePayloadSize} octets", ) elif 0 < self.maxFramePayloadSize < length: self.wasMaxFramePayloadSizeExceeded = True self._max_message_size_exceeded( length, self.maxFramePayloadSize, - "received WebSocket frame size {} exceeds payload limit of {} octets".format( - length, self.maxFramePayloadSize - ), + f"received WebSocket frame size {length} exceeds payload limit of {self.maxFramePayloadSize} octets", ) def onMessageFrameData(self, payload: bytes) -> None: @@ -663,9 +660,7 @@ def onMessageFrameData(self, payload: bytes) -> None: self._max_message_size_exceeded( self.message_data_total_length, self.maxMessagePayloadSize, - "received (partial) WebSocket message size {} (already) exceeds payload limit of {} octets".format( - self.message_data_total_length, self.maxMessagePayloadSize - ), + f"received (partial) WebSocket message size {self.message_data_total_length} (already) exceeds payload limit of {self.maxMessagePayloadSize} octets", ) self.message_data.append(payload) else: @@ -776,7 +771,7 @@ def onCloseFrame(self, code: int, reasonRaw: bytes) -> bool | None: ) or code >= 5000 ): - if self._protocol_violation("invalid close code {}".format(code)): + if self._protocol_violation(f"invalid close code {code}"): return True else: self.remoteCloseCode = WebSocketProtocol.CLOSE_STATUS_CODE_NORMAL @@ -1026,7 +1021,7 @@ def _fail_connection(self, code: int=CLOSE_STATUS_CODE_GOING_AWAY, reason: str=" # brutally drop the TCP connection self.wasClean = False self.wasNotCleanReason = ( - "I dropped the WebSocket TCP connection: {0}".format(reason) + f"I dropped the WebSocket TCP connection: {reason}" ) self.dropConnection(abort=True) @@ -1285,9 +1280,7 @@ def _connectionLost(self, reason: str) -> None: self._onClose( self.wasClean, WebSocketProtocol.CLOSE_STATUS_CODE_ABNORMAL_CLOSE, - 'connection was closed uncleanly ("{}")'.format( - self.wasNotCleanReason - ), + f'connection was closed uncleanly ("{self.wasNotCleanReason}")', ) else: self._onClose( @@ -1520,7 +1513,7 @@ def sendData(self, data: bytes, sync: bool=False, chopsize: int | None=None) -> if self.logOctets: self.logTxOctets(data, False) - def sendPreparedMessage(self, preparedMsg: "PreparedMessage") -> None: + def sendPreparedMessage(self, preparedMsg: PreparedMessage) -> None: """ Implements :func:`autobahn.websocket.interfaces.IWebSocketChannel.sendPreparedMessage` """ @@ -1563,7 +1556,7 @@ def processData(self) -> bool: pass else: if self._protocol_violation( - "RSV = {} and no extension negotiated".format(frame_rsv) + f"RSV = {frame_rsv} and no extension negotiated" ): return False @@ -1608,9 +1601,7 @@ def processData(self) -> bool: # if frame_opcode not in [8, 9, 10]: if self._protocol_violation( - "control frame using reserved opcode {}".format( - frame_opcode - ) + f"control frame using reserved opcode {frame_opcode}" ): return False @@ -1627,9 +1618,7 @@ def processData(self) -> bool: # if self._perMessageCompress is not None and frame_rsv == 4: if self._protocol_violation( - "received compressed control frame [{}]".format( - self._perMessageCompress.EXTENSION_NAME - ) + f"received compressed control frame [{self._perMessageCompress.EXTENSION_NAME}]" ): return False @@ -1638,7 +1627,7 @@ def processData(self) -> bool: # if frame_opcode not in [0, 1, 2]: if self._protocol_violation( - "data frame using reserved opcode {}".format(frame_opcode) + f"data frame using reserved opcode {frame_opcode}" ): return False @@ -1666,9 +1655,7 @@ def processData(self) -> bool: and self.inside_message ): if self._protocol_violation( - "received continuation data frame with compress bit set [{}]".format( - self._perMessageCompress.EXTENSION_NAME - ) + f"received continuation data frame with compress bit set [{self._perMessageCompress.EXTENSION_NAME}]" ): return False @@ -1888,9 +1875,7 @@ def onFrameData(self, payload: bytes) -> bool | None: self.utf8validateLast = self.utf8validator.validate(payload) if not self.utf8validateLast[0]: if self._invalid_payload( - "encountered invalid UTF-8 while processing text message at payload octet index {}".format( - self.utf8validateLast[3] - ) + f"encountered invalid UTF-8 while processing text message at payload octet index {self.utf8validateLast[3]}" ): return False @@ -1929,9 +1914,7 @@ def onFrameEnd(self) -> bool | None: if self.utf8validateIncomingCurrentMessage: if not self.utf8validateLast[1]: if self._invalid_payload( - "UTF-8 text message payload ended within Unicode code point at payload octet index {}".format( - self.utf8validateLast[3] - ) + f"UTF-8 text message payload ended within Unicode code point at payload octet index {self.utf8validateLast[3]}" ): return False @@ -2050,9 +2033,7 @@ def sendFrame( if payload_len is not None: if len(payload) < 1: raise Exception( - "cannot construct repeated payload with length {} from payload of length {}".format( - payload_len, len(payload) - ) + f"cannot construct repeated payload with length {payload_len} from payload of length {len(payload)}" ) l = payload_len pl = ( @@ -2138,9 +2119,7 @@ def sendPing(self, payload: bytes | None=None) -> None: l = len(payload) if l > 125: raise Exception( - "invalid payload for PING (payload length must be <= 125, was {})".format( - l - ) + f"invalid payload for PING (payload length must be <= 125, was {l})" ) self.sendFrame(opcode=9, payload=payload) else: @@ -2208,9 +2187,7 @@ def sendPong(self, payload=None): l = len(payload) if l > 125: raise Exception( - "invalid payload for PONG (payload length must be <= 125, was {})".format( - l - ) + f"invalid payload for PONG (payload length must be <= 125, was {l})" ) self.sendFrame(opcode=10, payload=payload) else: @@ -2268,9 +2245,7 @@ def sendClose(self, code: int | None=None, reason: str | None=None) -> None: if code is not None: if type(code) != int: raise Exception( - "invalid type '{}' for close code (must be an integer)".format( - type(code) - ) + f"invalid type '{type(code)}' for close code (must be an integer)" ) # 1000 Normal Closure @@ -2280,9 +2255,7 @@ def sendClose(self, code: int | None=None, reason: str | None=None) -> None: # if code != 1000 and not (3000 <= code <= 4999): raise Exception( - "invalid close code {} (must be 1000 or from [3000, 4999])".format( - code - ) + f"invalid close code {code} (must be 1000 or from [3000, 4999])" ) if reason is not None: @@ -2291,7 +2264,7 @@ def sendClose(self, code: int | None=None, reason: str | None=None) -> None: if type(reason) != str: raise Exception( - "reason must be of type unicode (was '{}')".format(type(reason)) + f"reason must be of type unicode (was '{type(reason)}')" ) reasonUtf8 = encode_truncate(reason, 123) @@ -2345,9 +2318,7 @@ def beginMessageFrame(self, length: int) -> None: WebSocketProtocol.SEND_STATE_INSIDE_MESSAGE, ]: raise Exception( - "WebSocketProtocol.beginMessageFrame invalid in current sending state [{}]".format( - self.send_state - ) + f"WebSocketProtocol.beginMessageFrame invalid in current sending state [{self.send_state}]" ) if type(length) != int or length < 0 or length > 0x7FFFFFFFFFFFFFFF: # 2**63 @@ -2529,21 +2500,17 @@ def sendMessage( Implements :func:`autobahn.websocket.interfaces.IWebSocketChannel.sendMessage` """ assert type(payload) == bytes, ( - '"payload" must have type bytes, but was "{}"'.format(type(payload)) + f'"payload" must have type bytes, but was "{type(payload)}"' ) assert type(isBinary) == bool, ( - '"isBinary" must have type bool, but was "{}"'.format(type(isBinary)) + f'"isBinary" must have type bool, but was "{type(isBinary)}"' ) assert fragmentSize is None or type(fragmentSize) == int, ( - '"fragmentSize" must have type int, but was "{}"'.format(type(fragmentSize)) - ) - assert type(sync) == bool, '"sync" must have type bool, but was "{}"'.format( - type(sync) + f'"fragmentSize" must have type int, but was "{type(fragmentSize)}"' ) + assert type(sync) == bool, f'"sync" must have type bool, but was "{type(sync)}"' assert type(doNotCompress) == bool, ( - '"doNotCompress" must have type bool, but was "{}"'.format( - type(doNotCompress) - ) + f'"doNotCompress" must have type bool, but was "{type(doNotCompress)}"' ) if self.state != WebSocketProtocol.STATE_OPEN: @@ -2586,9 +2553,7 @@ def sendMessage( if 0 < self.maxMessagePayloadSize < payload_len: self.wasMaxMessagePayloadSizeExceeded = True - emsg = "tried to send WebSocket message with size {} exceeding payload limit of {} octets".format( - payload_len, self.maxMessagePayloadSize - ) + emsg = f"tried to send WebSocket message with size {payload_len} exceeding payload limit of {self.maxMessagePayloadSize} octets" self.log.warn(emsg) raise PayloadExceededError(emsg) @@ -2617,7 +2582,7 @@ def sendMessage( else: if pfs < 1: raise Exception( - "payload fragment size must be at least 1 (was {})".format(pfs) + f"payload fragment size must be at least 1 (was {pfs})" ) n = len(payload) i = 0 @@ -2679,7 +2644,7 @@ def _parseExtensionsHeader(self, header, removeQuotes=True): IWebSocketChannelStreamingApi.register(WebSocketProtocol) -class PreparedMessage(object): +class PreparedMessage: """ Encapsulates a prepared message to be sent later once or multiple times on one or more WebSocket connections. @@ -2748,7 +2713,7 @@ def __init__(self, payload: bytes, isBinary: bool, applyMask: bool, doNotCompres ) -class WebSocketFactory(object): +class WebSocketFactory: """ Mixin for :class:`autobahn.websocket.protocol.WebSocketClientFactory` and @@ -2915,9 +2880,7 @@ def processHandshake(self) -> None: ) except Exception as e: return self.failHandshake( - "Error during parsing of HTTP status line / request headers : {0}".format( - e - ) + f"Error during parsing of HTTP status line / request headers : {e}" ) # replace self.peer if the x-forwarded-for header is present and trusted @@ -2945,16 +2908,16 @@ def processHandshake(self) -> None: rl = self.http_status_line.split() if len(rl) != 3: return self.failHandshake( - 'Bad HTTP request status line "{}"'.format(self.http_status_line) + f'Bad HTTP request status line "{self.http_status_line}"' ) if rl[0].strip() != "GET": return self.failHandshake( - 'HTTP method "{}" not allowed'.format(rl[0]), 405 + f'HTTP method "{rl[0]}" not allowed', 405 ) vs = rl[2].strip().split("/") if len(vs) != 2 or vs[0] != "HTTP" or vs[1] not in ["1.1"]: return self.failHandshake( - 'Unsupported HTTP version "{}"'.format(rl[2]), 505 + f'Unsupported HTTP version "{rl[2]}"', 505 ) # HTTP Request line : REQUEST-URI @@ -2974,9 +2937,7 @@ def processHandshake(self) -> None: # URIs, and MUST NOT be used on these URIs. if fragment != "": return self.failHandshake( - 'HTTP requested resource contains a fragment identifier "{}"'.format( - fragment - ) + f'HTTP requested resource contains a fragment identifier "{fragment}"' ) # resource path and query parameters .. this will get forwarded @@ -2985,9 +2946,7 @@ def processHandshake(self) -> None: self.http_request_params = parse.parse_qs(query) except: return self.failHandshake( - 'Bad HTTP request resource - could not parse "{}"'.format( - rl[1].strip() - ) + f'Bad HTTP request resource - could not parse "{rl[1].strip()}"' ) # Host @@ -3012,20 +2971,14 @@ def processHandshake(self) -> None: port = int(str(p.strip())) except ValueError: return self.failHandshake( - 'invalid port "{}" in HTTP Host header "{}"'.format( - str(p.strip()), str(self.http_request_host) - ) + f'invalid port "{str(p.strip())}" in HTTP Host header "{str(self.http_request_host)}"' ) # do port checking only if externalPort was set if self.factory.externalPort: if port != self.factory.externalPort: return self.failHandshake( - 'port {} in HTTP Host header "{}" does not match server listening port {}'.format( - port, - str(self.http_request_host), - self.factory.externalPort, - ) + f'port {port} in HTTP Host header "{str(self.http_request_host)}" does not match server listening port {self.factory.externalPort}' ) else: self.log.debug( @@ -3149,9 +3102,7 @@ def processHandshake(self) -> None: sv.reverse() svs = ",".join([str(x) for x in sv]) return self.failHandshake( - "WebSocket version {} not supported (supported versions: {})".format( - version, svs - ), + f"WebSocket version {version} not supported (supported versions: {svs})", 400, # Bad Request [("Sec-WebSocket-Version", svs)], ) @@ -3171,9 +3122,7 @@ def processHandshake(self) -> None: for p in protocols: if p in pp: return self.failHandshake( - 'duplicate protocol "{}" specified in HTTP Sec-WebSocket-Protocol header'.format( - p - ) + f'duplicate protocol "{p}" specified in HTTP Sec-WebSocket-Protocol header' ) else: pp[p] = 1 @@ -3205,7 +3154,7 @@ def processHandshake(self) -> None: origin_tuple = _url_to_origin(self.websocket_origin) except ValueError as e: return self.failHandshake( - "HTTP Origin header invalid: {}".format(e) + f"HTTP Origin header invalid: {e}" ) have_origin = True else: @@ -3224,9 +3173,7 @@ def processHandshake(self) -> None: ) if not origin_is_allowed: return self.failHandshake( - "WebSocket connection denied: origin '{0}' not allowed".format( - self.websocket_origin - ) + f"WebSocket connection denied: origin '{self.websocket_origin}' not allowed" ) # Sec-WebSocket-Key @@ -3240,13 +3187,11 @@ def processHandshake(self) -> None: key = self.http_headers["sec-websocket-key"].strip() if len(key) != 24: # 16 bytes => (ceil(128/24)*24)/6 == 24 return self.failHandshake( - 'bad Sec-WebSocket-Key (length must be 24 ASCII chars) "{}"'.format( - key - ) + f'bad Sec-WebSocket-Key (length must be 24 ASCII chars) "{key}"' ) if key[-2:] != "==": # 24 - ceil(128/6) == 2 return self.failHandshake( - 'bad Sec-WebSocket-Key (invalid base64 encoding) "{}"'.format(key) + f'bad Sec-WebSocket-Key (invalid base64 encoding) "{key}"' ) for c in key[:-2]: if ( @@ -3254,9 +3199,7 @@ def processHandshake(self) -> None: not in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/" ): return self.failHandshake( - 'bad character "{}" in Sec-WebSocket-Key (invalid base64 encoding) "{}"'.format( - c, key - ) + f'bad character "{c}" in Sec-WebSocket-Key (invalid base64 encoding) "{key}"' ) # Sec-WebSocket-Extensions @@ -3329,7 +3272,7 @@ def forward_error(err): ) self.log.warn("{tb}", tb=txaio.failure_format_traceback(err)) return self.failHandshake( - "Internal server error: {}".format(err.value), + f"Internal server error: {err.value}", ConnectionDeny.INTERNAL_SERVER_ERROR, ) @@ -3442,7 +3385,7 @@ def succeedHandshake(self, res) -> None: response = "HTTP/1.1 101 Switching Protocols\x0d\x0a" if self.factory.server: - response += "Server: {}\x0d\x0a".format(self.factory.server) + response += f"Server: {self.factory.server}\x0d\x0a" response += "Upgrade: WebSocket\x0d\x0a" response += "Connection: Upgrade\x0d\x0a" @@ -3452,7 +3395,7 @@ def succeedHandshake(self, res) -> None: # headers from factory, headers from onConnect for headers_source in (self.factory.headers.items(), headers.items()): for uh in headers_source: - if isinstance(uh[1], (str,)): + if isinstance(uh[1], str): header_values = [uh[1]] else: try: @@ -3461,12 +3404,10 @@ def succeedHandshake(self, res) -> None: header_values = [uh[1]] for header_value in header_values: - response += "{}: {}\x0d\x0a".format(uh[0], header_value) + response += f"{uh[0]}: {header_value}\x0d\x0a" if self.websocket_protocol_in_use is not None: - response += "Sec-WebSocket-Protocol: {}\x0d\x0a".format( - self.websocket_protocol_in_use - ) + response += f"Sec-WebSocket-Protocol: {self.websocket_protocol_in_use}\x0d\x0a" # compute Sec-WebSocket-Accept # @@ -3475,9 +3416,7 @@ def succeedHandshake(self, res) -> None: sha1.update(key.encode("utf8") + WebSocketProtocol._WS_MAGIC) sec_websocket_accept = base64.b64encode(sha1.digest()) - response += "Sec-WebSocket-Accept: {}\x0d\x0a".format( - sec_websocket_accept.decode() - ) + response += f"Sec-WebSocket-Accept: {sec_websocket_accept.decode()}\x0d\x0a" # agreed extensions # @@ -3557,10 +3496,10 @@ def sendHttpErrorResponse(self, code, reason, responseHeaders=None): """ Send out HTTP error response. """ - response = "HTTP/1.1 {0} {1}\x0d\x0a".format(code, reason) + response = f"HTTP/1.1 {code} {reason}\x0d\x0a" if responseHeaders: for h in responseHeaders: - response += "{0}: {1}\x0d\x0a".format(h[0], h[1]) + response += f"{h[0]}: {h[1]}\x0d\x0a" response += "\x0d\x0a" self.sendData(response.encode("utf8")) @@ -3571,9 +3510,9 @@ def sendHtml(self, html: str) -> None: responseBody = html.encode("utf8") response = "HTTP/1.1 200 OK\x0d\x0a" if self.factory.server is not None and self.factory.server != "": - response += "Server: {}\x0d\x0a".format(self.factory.server) + response += f"Server: {self.factory.server}\x0d\x0a" response += "Content-Type: text/html; charset=UTF-8\x0d\x0a" - response += "Content-Length: {}\x0d\x0a".format(len(responseBody)) + response += f"Content-Length: {len(responseBody)}\x0d\x0a" response += "\x0d\x0a" self.sendData(response.encode("utf8")) self.sendData(responseBody) @@ -3584,8 +3523,8 @@ def sendRedirect(self, url: str) -> None: """ response = "HTTP/1.1 303\x0d\x0a" if self.factory.server is not None and self.factory.server != "": - response += "Server: {}\x0d\x0a".format(self.factory.server) - response += "Location: {}\x0d\x0a".format(url) + response += f"Server: {self.factory.server}\x0d\x0a" + response += f"Location: {url}\x0d\x0a" response += "\x0d\x0a" self.sendData(response.encode("utf8")) @@ -3595,9 +3534,7 @@ def sendServerStatus(self, redirectUrl: str | None=None, redirectAfter: int=0) - upgrade to WebSocket header (and option serverStatus is True). """ if redirectUrl: - redirect = """""".format( - redirectAfter, redirectUrl - ) + redirect = f"""""" else: redirect = "" self.sendHtml(_SERVER_STATUS_TEMPLATE.format(redirect, __version__)) @@ -3624,7 +3561,7 @@ def __init__( self, url=None, protocols=None, - server="AutobahnPython/{}".format(__version__), + server=f"AutobahnPython/{__version__}", headers=None, externalPort=None, ): @@ -3765,9 +3702,7 @@ def setProtocolOptions( for v in versions: if v not in WebSocketProtocol.SUPPORTED_PROTOCOL_VERSIONS: raise Exception( - "invalid WebSocket protocol version {} (allowed values: {})".format( - v, WebSocketProtocol.SUPPORTED_PROTOCOL_VERSIONS - ) + f"invalid WebSocket protocol version {v} (allowed values: {WebSocketProtocol.SUPPORTED_PROTOCOL_VERSIONS})" ) if set(versions) != set(self.versions): self.versions = versions @@ -3975,10 +3910,8 @@ def startProxyConnect(self): """ # construct proxy connect HTTP request # - request = "CONNECT {}:{} HTTP/1.1\x0d\x0a".format( - self.factory.host, self.factory.port - ) - request += "Host: {}:{}\x0d\x0a".format(self.factory.host, self.factory.port) + request = f"CONNECT {self.factory.host}:{self.factory.port} HTTP/1.1\x0d\x0a" + request += f"Host: {self.factory.host}:{self.factory.port}\x0d\x0a" request += "\x0d\x0a" self.log.debug("{request}", request=request) @@ -4021,7 +3954,7 @@ def processProxyConnect(self): sl = http_status_line.split() if len(sl) < 2: return self.failProxyConnect( - 'Bad HTTP response status line "{}"'.format(http_status_line) + f'Bad HTTP response status line "{http_status_line}"' ) # HTTP version @@ -4029,7 +3962,7 @@ def processProxyConnect(self): http_version = sl[0].strip() if http_version not in ("HTTP/1.1", "HTTP/1.0"): return self.failProxyConnect( - 'Unsupported HTTP version "{}"'.format(http_version) + f'Unsupported HTTP version "{http_version}"' ) # HTTP status code @@ -4038,7 +3971,7 @@ def processProxyConnect(self): status_code = int(sl[1].strip()) except ValueError: return self.failProxyConnect( - 'Bad HTTP status code "{}"'.format(sl[1].strip()) + f'Bad HTTP status code "{sl[1].strip()}"' ) if not (200 <= status_code < 300): @@ -4050,7 +3983,7 @@ def processProxyConnect(self): else: reason = "" return self.failProxyConnect( - 'HTTP proxy connect failed ({}): "{}"'.format(status_code, reason) + f'HTTP proxy connect failed ({status_code}): "{reason}"' ) # Ok, got complete response for HTTP/CONNECT, remember rest (if any) @@ -4138,14 +4071,12 @@ def _actuallyStartHandshake(self, request_options): """ # construct WS opening handshake HTTP header # - request = "GET {} HTTP/1.1\x0d\x0a".format(request_options.resource) + request = f"GET {request_options.resource} HTTP/1.1\x0d\x0a" if request_options.useragent is not None and request_options.useragent != "": - request += "User-Agent: {}\x0d\x0a".format(request_options.useragent) + request += f"User-Agent: {request_options.useragent}\x0d\x0a" - request += "Host: {}:{}\x0d\x0a".format( - request_options.host, request_options.port - ) + request += f"Host: {request_options.host}:{request_options.port}\x0d\x0a" request += "Upgrade: WebSocket\x0d\x0a" request += "Connection: Upgrade\x0d\x0a" @@ -4161,22 +4092,20 @@ def _actuallyStartHandshake(self, request_options): # optional, user supplied additional HTTP headers # for uh in request_options.headers.items(): - request += "{}: {}\x0d\x0a".format(uh[0], uh[1]) + request += f"{uh[0]}: {uh[1]}\x0d\x0a" # handshake random key # self.websocket_key = base64.b64encode(os.urandom(16)) - request += "Sec-WebSocket-Key: {}\x0d\x0a".format(self.websocket_key.decode()) + request += f"Sec-WebSocket-Key: {self.websocket_key.decode()}\x0d\x0a" # optional origin announced # if request_options.origin: if self.version > 10: - request += "Origin: {}\x0d\x0a".format(request_options.origin) + request += f"Origin: {request_options.origin}\x0d\x0a" else: - request += "Sec-WebSocket-Origin: {}\x0d\x0a".format( - request_options.origin - ) + request += f"Sec-WebSocket-Origin: {request_options.origin}\x0d\x0a" # optional list of WS subprotocols announced # @@ -4201,9 +4130,7 @@ def _actuallyStartHandshake(self, request_options): # set WS protocol version # - request += "Sec-WebSocket-Version: {}\x0d\x0a".format( - WebSocketProtocol.SPEC_TO_PROTOCOL_VERSION[self.version] - ) + request += f"Sec-WebSocket-Version: {WebSocketProtocol.SPEC_TO_PROTOCOL_VERSION[self.version]}\x0d\x0a" request += "\x0d\x0a" @@ -4253,7 +4180,7 @@ def processHandshake(self): sl = self.http_status_line.split() if len(sl) < 2: return self.failHandshake( - 'Bad HTTP response status line "{}"'.format(self.http_status_line) + f'Bad HTTP response status line "{self.http_status_line}"' ) # HTTP version @@ -4261,7 +4188,7 @@ def processHandshake(self): http_version = sl[0].strip() if http_version != "HTTP/1.1": return self.failHandshake( - 'Unsupported HTTP version "{}"'.format(http_version) + f'Unsupported HTTP version "{http_version}"' ) # HTTP status code @@ -4270,7 +4197,7 @@ def processHandshake(self): status_code = int(sl[1].strip()) except ValueError: return self.failHandshake( - 'Bad HTTP status code "{}"'.format(sl[1].strip()) + f'Bad HTTP status code "{sl[1].strip()}"' ) if status_code != 101: # Switching Protocols # FIXME: handle redirects @@ -4281,9 +4208,7 @@ def processHandshake(self): else: reason = "" return self.failHandshake( - "WebSocket connection upgrade failed [{}]: {}".format( - status_code, reason - ) + f"WebSocket connection upgrade failed [{status_code}]: {reason}" ) # Upgrade @@ -4334,9 +4259,7 @@ def processHandshake(self): if sec_websocket_accept_got != sec_websocket_accept: return self.failHandshake( - "HTTP Sec-WebSocket-Accept bogus value : expected {} / got {}".format( - sec_websocket_accept, sec_websocket_accept_got - ) + f"HTTP Sec-WebSocket-Accept bogus value : expected {sec_websocket_accept} / got {sec_websocket_accept_got}" ) # Sec-WebSocket-Extensions @@ -4401,9 +4324,7 @@ def processHandshake(self): else: return self.failHandshake( - 'server wants to use extension "{}" we did not request, have not implemented or did not enable'.format( - extension - ) + f'server wants to use extension "{extension}" we did not request, have not implemented or did not enable' ) # handle "subprotocol in use" - if any @@ -4418,9 +4339,7 @@ def processHandshake(self): if sp != "": if sp not in self.factory.protocols: return self.failHandshake( - 'subprotocol selected by server "{}" not in subprotocol list requested by client "{}"'.format( - sp, self.factory.protocols - ) + f'subprotocol selected by server "{sp}" not in subprotocol list requested by client "{self.factory.protocols}"' ) else: # ok, subprotocol in use @@ -4486,7 +4405,7 @@ def on_connect_failed(fail): "onConnect failed with {fail}", fail=fail, ) - self._fail_connection(1000, "{}".format(fail)) + self._fail_connection(1000, f"{fail}") txaio.add_callbacks(d, on_connect_success, on_connect_failed) return d @@ -4526,7 +4445,7 @@ def __init__( url=None, origin=None, protocols=None, - useragent="AutobahnPython/{}".format(__version__), + useragent=f"AutobahnPython/{__version__}", headers=None, proxy=None, ): @@ -4647,9 +4566,7 @@ def setProtocolOptions( if version is not None: if version not in WebSocketProtocol.SUPPORTED_SPEC_VERSIONS: raise Exception( - "invalid WebSocket draft version {} (allowed values: {})".format( - version, WebSocketProtocol.SUPPORTED_SPEC_VERSIONS - ) + f"invalid WebSocket draft version {version} (allowed values: {WebSocketProtocol.SUPPORTED_SPEC_VERSIONS})" ) if version != self.version: self.version = version @@ -4729,9 +4646,7 @@ def setProtocolOptions( ) else: raise Exception( - "invalid type {} for perMessageCompressionOffers - expected list".format( - type(perMessageCompressionOffers) - ) + f"invalid type {type(perMessageCompressionOffers)} for perMessageCompressionOffers - expected list" ) if ( diff --git a/src/autobahn/websocket/types.py b/src/autobahn/websocket/types.py index ca7b24df9..61f8de503 100644 --- a/src/autobahn/websocket/types.py +++ b/src/autobahn/websocket/types.py @@ -42,7 +42,7 @@ @public -class ConnectionRequest(object): +class ConnectionRequest: """ Thin-wrapper for WebSocket connection request information provided in :meth:`autobahn.websocket.protocol.WebSocketServerProtocol.onConnect` when @@ -131,7 +131,7 @@ def __str__(self): @public -class ConnectingRequest(object): +class ConnectingRequest: """ Thin-wrapper for WebSocket connection request information provided in :meth:`autobahn.websocket.protocol.WebSocketClientProtocol.onConnecting` @@ -204,7 +204,7 @@ def __str__(self): @public -class ConnectionResponse(object): +class ConnectionResponse: """ Thin-wrapper for WebSocket connection response information provided in :meth:`autobahn.websocket.protocol.WebSocketClientProtocol.onConnect` when @@ -252,7 +252,7 @@ def __str__(self): @public -class ConnectionAccept(object): +class ConnectionAccept: """ Used by WebSocket servers to accept an incoming WebSocket connection. If the client announced one or multiple subprotocols, the server MUST @@ -355,7 +355,7 @@ def __init__(self, code, reason=None): self.reason = reason -class Message(object): +class Message: """ Abstract base class for WebSocket messages. """ @@ -421,7 +421,7 @@ def __init__(self, payload, is_binary=False, skip_compress=False): self.skip_compress = skip_compress -class Ping(object): +class Ping: """ A WebSocket ping message. """ @@ -435,15 +435,11 @@ def __init__(self, payload=None): :type payload: bytes or None """ assert payload is None or type(payload) == bytes, ( - "invalid type {} for WebSocket ping payload - must be None or bytes".format( - type(payload) - ) + f"invalid type {type(payload)} for WebSocket ping payload - must be None or bytes" ) if payload is not None: assert len(payload) < 126, ( - "WebSocket ping payload too long ({} bytes) - must be <= 125 bytes".format( - len(payload) - ) + f"WebSocket ping payload too long ({len(payload)} bytes) - must be <= 125 bytes" ) self.payload = payload diff --git a/src/autobahn/websocket/utf8validator.py b/src/autobahn/websocket/utf8validator.py index 6a0acf2c1..d6f3f513f 100644 --- a/src/autobahn/websocket/utf8validator.py +++ b/src/autobahn/websocket/utf8validator.py @@ -456,7 +456,7 @@ # convert DFA table to bytes (performance) UTF8VALIDATOR_DFA_S = bytes(UTF8VALIDATOR_DFA) - class Utf8Validator(object): + class Utf8Validator: """ Incremental UTF-8 validator with constant memory consumption (minimal state). diff --git a/src/autobahn/websocket/util.py b/src/autobahn/websocket/util.py index f22435919..04bcd1d18 100644 --- a/src/autobahn/websocket/util.py +++ b/src/autobahn/websocket/util.py @@ -80,17 +80,17 @@ def create_url(hostname, port=None, isSecure=False, path=None, params=None): assert type(isSecure) == bool if hostname == "unix": - netloc = "unix:%s" % port + netloc = f"unix:{port}" else: assert port is None or (type(port) == int and port in range(0, 65535)) if port is not None: - netloc = "%s:%d" % (hostname, port) + netloc = f"{hostname}:{port}" else: if isSecure: - netloc = "%s:443" % hostname + netloc = f"{hostname}:443" else: - netloc = "%s:80" % hostname + netloc = f"{hostname}:80" if isSecure: scheme = "wss" @@ -139,9 +139,7 @@ def parse_url(url): if parsed.scheme not in ["ws", "wss"]: raise ValueError( - "invalid WebSocket URL: protocol scheme '{}' is not for WebSocket".format( - parsed.scheme - ) + f"invalid WebSocket URL: protocol scheme '{parsed.scheme}' is not for WebSocket" ) if not parsed.hostname or parsed.hostname == "": @@ -149,7 +147,7 @@ def parse_url(url): if parsed.fragment is not None and parsed.fragment != "": raise ValueError( - "invalid WebSocket URL: non-empty fragment '%s" % parsed.fragment + f"invalid WebSocket URL: non-empty fragment '{parsed.fragment}'" ) if parsed.path is not None and parsed.path != "": @@ -189,6 +187,6 @@ def parse_url(url): tcp_port = int(parsed.port) if tcp_port < 1 or tcp_port > 65535: - raise ValueError("invalid port {}".format(tcp_port)) + raise ValueError(f"invalid port {tcp_port}") return parsed.scheme == "wss", parsed.hostname, tcp_port, resource, path, params diff --git a/src/autobahn/websocket/xormasker.py b/src/autobahn/websocket/xormasker.py index 08d1c02df..9e4682496 100644 --- a/src/autobahn/websocket/xormasker.py +++ b/src/autobahn/websocket/xormasker.py @@ -27,7 +27,7 @@ # XorMaskerNull: pass-through implementation (no masking applied) # Shared by all implementations (NVX, pure Python) -class XorMaskerNull(object): +class XorMaskerNull: __slots__ = ("_ptr",) # noinspection PyUnusedLocal @@ -65,7 +65,7 @@ def process(self, data): from array import array - class XorMaskerSimple(object): + class XorMaskerSimple: __slots__ = ("_ptr", "_msk") def __init__(self, mask): @@ -87,7 +87,7 @@ def process(self, data): self._ptr += 1 return payload.tobytes() - class XorMaskerShifted1(object): + class XorMaskerShifted1: __slots__ = ("_ptr", "_mskarray") def __init__(self, mask):