From 7c6dfc3a7f177cb17609906d84dbd495e12a6e6c Mon Sep 17 00:00:00 2001 From: totaam Date: Sun, 28 May 2023 22:16:13 +0700 Subject: [PATCH] more mostly automatic type hints --- xpra/audio/sink.py | 5 +- xpra/audio/src.py | 3 +- xpra/audio/wrapper.py | 5 +- xpra/client/base/client_base.py | 123 +++++++++--------- xpra/client/base/fileprint_mixin.py | 34 ++--- xpra/client/base/stub_client_mixin.py | 6 +- xpra/client/gl/gl_check.py | 4 +- xpra/client/gl/gl_window_backing_base.py | 11 +- xpra/client/gtk_base/gtk_client_base.py | 5 +- xpra/client/gui/ui_client_base.py | 91 ++++++------- xpra/client/mixins/display.py | 67 +++++----- xpra/client/mixins/encodings.py | 7 +- xpra/client/mixins/network_listener.py | 25 ++-- xpra/client/mixins/notifications.py | 6 +- xpra/client/mixins/webcam.py | 3 +- xpra/clipboard/clipboard_core.py | 5 +- xpra/codecs/argb/encoder.py | 6 +- xpra/codecs/ffmpeg/colorspace_converter.pyx | 6 +- xpra/codecs/ffmpeg/decoder.pyx | 5 +- xpra/codecs/ffmpeg/encoder.pyx | 6 +- xpra/codecs/gstreamer/codec_common.py | 15 +-- xpra/codecs/gstreamer/encoder.py | 2 +- xpra/codecs/jpeg/encoder.pyx | 5 +- xpra/codecs/libyuv/colorspace_converter.pyx | 5 +- xpra/codecs/nvidia/nvdec/decoder.pyx | 7 +- xpra/codecs/nvidia/nvenc/encoder.pyx | 7 +- .../codecs/nvidia/nvfbc/fbc_capture_linux.pyx | 9 +- xpra/codecs/nvidia/nvfbc/fbc_capture_win.pyx | 9 +- xpra/codecs/nvidia/nvjpeg/encoder.pyx | 5 +- xpra/codecs/openh264/decoder.pyx | 6 +- xpra/codecs/openh264/encoder.pyx | 3 +- xpra/codecs/pillow/decoder.py | 4 +- xpra/codecs/pillow/encoder.py | 4 +- xpra/codecs/proxy/encoder.py | 39 +++--- xpra/codecs/v4l2/pusher.pyx | 6 +- xpra/codecs/vpx/decoder.pyx | 58 +++++---- xpra/codecs/vpx/encoder.pyx | 7 +- xpra/codecs/webp/encoder.pyx | 5 +- xpra/codecs/x264/encoder.pyx | 55 ++++---- xpra/codecs/x265/encoder.pyx | 2 +- xpra/dbus/notifications_forwarder.py | 5 +- xpra/gtk_common/gtk_clipboard.py | 2 +- xpra/gtk_common/gtk_util.py | 2 +- xpra/keyboard/layouts.py | 12 +- xpra/log.py | 6 +- xpra/net/compression.py | 4 +- xpra/net/crypto.py | 7 +- xpra/net/file_transfer.py | 67 +++++----- xpra/net/mdns/avahi_publisher.py | 8 +- xpra/net/net_util.py | 6 +- xpra/net/protocol/socket_handler.py | 5 +- xpra/net/quic/connection.py | 4 +- xpra/net/quic/websocket.py | 6 +- xpra/net/socket_util.py | 21 +-- xpra/net/ssh/paramiko_client.py | 7 +- xpra/net/subprocess_wrapper.py | 7 +- xpra/notifications/dbus_notifier.py | 7 +- xpra/os_util.py | 2 +- xpra/platform/darwin/osx_clipboard.py | 2 +- xpra/platform/darwin/shadow_server.py | 45 ++++--- xpra/platform/gui.py | 5 +- xpra/platform/posix/webcam.py | 5 +- xpra/platform/win32/clipboard.py | 2 +- xpra/platform/win32/gdi_screen_capture.py | 25 ++-- xpra/platform/win32/namedpipes/connection.py | 5 +- xpra/platform/win32/win32_notifier.py | 17 +-- xpra/scripts/config.py | 6 +- xpra/scripts/main.py | 88 +++++++------ xpra/scripts/parsing.py | 27 ++-- xpra/scripts/server.py | 5 +- xpra/server/gtk_server_base.py | 9 +- xpra/server/keyboard_config_base.py | 6 +- xpra/server/menu_provider.py | 7 +- xpra/server/mixins/audio_server.py | 11 +- xpra/server/mixins/child_command_server.py | 15 ++- xpra/server/mixins/clipboard_server.py | 37 +++--- xpra/server/mixins/dbusrpc_server.py | 19 +-- xpra/server/mixins/display_manager.py | 14 +- xpra/server/mixins/encoding_server.py | 6 +- xpra/server/mixins/logging_server.py | 39 +++--- xpra/server/mixins/mmap_server.py | 5 +- xpra/server/mixins/networkstate_server.py | 31 ++--- xpra/server/mixins/notification_forwarder.py | 38 +++--- xpra/server/mixins/shell_server.py | 8 +- xpra/server/mixins/stub_server_mixin.py | 14 +- xpra/server/mixins/webcam_server.py | 7 +- xpra/server/mixins/window_server.py | 58 +++++---- xpra/server/pam.pyx | 6 +- xpra/server/proxy/proxy_instance.py | 7 +- xpra/server/rfb/rfb_source.py | 5 +- xpra/server/server_base.py | 28 ++-- xpra/server/server_core.py | 40 +++--- xpra/server/shadow/root_window_model.py | 5 +- xpra/server/source/audio_mixin.py | 7 +- xpra/server/source/avsync_mixin.py | 6 +- xpra/server/source/client_connection.py | 5 +- .../source/client_connection_factory.py | 6 +- xpra/server/source/clipboard_connection.py | 5 +- xpra/server/source/encodings_mixin.py | 7 +- xpra/server/source/fileprint_mixin.py | 5 +- xpra/server/source/idle_mixin.py | 6 +- xpra/server/source/input_mixin.py | 6 +- xpra/server/source/mmap_connection.py | 5 +- xpra/server/source/notification_mixin.py | 4 +- xpra/server/source/shell_mixin.py | 7 +- xpra/server/source/source_stats.py | 5 +- xpra/server/source/stub_source_mixin.py | 7 +- xpra/server/source/webcam_mixin.py | 6 +- xpra/server/source/windows_mixin.py | 9 +- xpra/server/window/metadata.py | 7 +- xpra/server/window/video_subregion.py | 5 +- xpra/server/window/window_source.py | 4 +- xpra/server/window/window_stats.py | 3 +- xpra/server/window/window_video_source.py | 10 +- xpra/server/window/windowicon_source.py | 5 +- xpra/util.py | 2 +- xpra/x11/bindings/window.pyx | 5 +- xpra/x11/common.py | 6 +- xpra/x11/desktop/desktop_server_base.py | 3 +- xpra/x11/desktop/monitor_server.py | 5 +- xpra/x11/gtk_x11/wm_check.py | 4 +- xpra/x11/models/core.py | 3 +- xpra/x11/server.py | 9 +- xpra/x11/shadow_x11_server.py | 6 +- xpra/x11/x11_server_base.py | 7 +- xpra/x11/x11_server_core.py | 15 ++- 126 files changed, 914 insertions(+), 782 deletions(-) diff --git a/xpra/audio/sink.py b/xpra/audio/sink.py index 992a480fb3..c46d7a5d5e 100755 --- a/xpra/audio/sink.py +++ b/xpra/audio/sink.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # This file is part of Xpra. -# Copyright (C) 2010-2022 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -8,6 +8,7 @@ from time import monotonic from collections import deque from threading import Lock +from typing import Dict from gi.repository import GObject # @UnresolvedImport from xpra.audio.audio_pipeline import AudioPipeline @@ -342,7 +343,7 @@ def eos(self): self.cleanup() return GST_FLOW_OK - def get_info(self) -> dict: + def get_info(self) -> Dict: info = super().get_info() if QUEUE_TIME>0 and self.queue: clt = self.queue.get_property("current-level-time") diff --git a/xpra/audio/src.py b/xpra/audio/src.py index f1da6fd1c9..34c14ef533 100755 --- a/xpra/audio/src.py +++ b/xpra/audio/src.py @@ -8,6 +8,7 @@ import os.path from queue import Queue from time import monotonic +from typing import Dict from gi.repository import GObject # @UnresolvedImport from xpra.os_util import SIGNAMES @@ -184,7 +185,7 @@ def cleanup(self): self.sink = None self.caps = None - def get_info(self) -> dict: + def get_info(self) -> Dict: info = super().get_info() if self.queue: info["queue"] = {"cur" : self.queue.get_property("current-level-time")//MS_TO_NS} diff --git a/xpra/audio/wrapper.py b/xpra/audio/wrapper.py index b416f34841..d6eb029ea9 100644 --- a/xpra/audio/wrapper.py +++ b/xpra/audio/wrapper.py @@ -1,5 +1,5 @@ # This file is part of Xpra. -# Copyright (C) 2015-2020 Antoine Martin +# Copyright (C) 2015-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -7,6 +7,7 @@ import sys from time import monotonic from collections import namedtuple +from typing import Dict from xpra.gst_common import import_gst, format_element_options from xpra.audio.gstreamer_util import ( @@ -299,7 +300,7 @@ def get_state(self): return self.state - def get_info(self) -> dict: + def get_info(self) -> Dict: return self.info def info_update(self, _wrapper, info): diff --git a/xpra/client/base/client_base.py b/xpra/client/base/client_base.py index ea090b2a33..2baa57f74d 100644 --- a/xpra/client/base/client_base.py +++ b/xpra/client/base/client_base.py @@ -1,5 +1,5 @@ # This file is part of Xpra. -# Copyright (C) 2010-2022 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Copyright (C) 2008, 2010 Nathaniel Smith # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -11,6 +11,7 @@ import socket import string from time import monotonic +from typing import Dict, Any, Callable from xpra.log import Logger from xpra.scripts.config import InitExit @@ -245,7 +246,7 @@ def get_challenge_handler(self, auth, import_error_logger): return None - def may_notify(self, nid, summary, body, *args, **kwargs): + def may_notify(self, nid:int, summary:str, body:str, *args, **kwargs): notifylog = Logger("notify") notifylog("may_notify(%s, %s, %s, %s, %s)", nid, summary, body, args, kwargs) notifylog.info("%s", summary) @@ -254,13 +255,13 @@ def may_notify(self, nid, summary, body, *args, **kwargs): notifylog.info(" %s", x) - def handle_deadly_signal(self, signum, _frame=None): + def handle_deadly_signal(self, signum:int, _frame=None): sys.stderr.write("\ngot deadly signal %s, exiting\n" % SIGNAMES.get(signum, signum)) sys.stderr.flush() self.cleanup() force_quit(128 + signum) - def handle_app_signal(self, signum, _frame=None): + def handle_app_signal(self, signum:int, _frame=None): try: log.info("exiting") except Exception: @@ -271,7 +272,7 @@ def handle_app_signal(self, signum, _frame=None): reason = "exit on signal %s" % SIGNAMES.get(signum, signum) self.timeout_add(0, self.signal_disconnect_and_quit, 128 + signum, reason) - def install_signal_handlers(self): + def install_signal_handlers(self) -> None: def os_signal(signum, _frame=None): if self.exit_code is None: try: @@ -285,7 +286,7 @@ def os_signal(signum, _frame=None): signal.signal(signal.SIGTERM, os_signal) register_SIGUSR_signals(self.idle_add) - def signal_disconnect_and_quit(self, exit_code, reason): + def signal_disconnect_and_quit(self, exit_code:int, reason:str) -> None: log("signal_disconnect_and_quit(%s, %s) exit_on_signal=%s", exit_code, reason, self.exit_on_signal) if not self.exit_on_signal: #if we get another signal, we'll try to exit without idle_add... @@ -300,12 +301,12 @@ def signal_disconnect_and_quit(self, exit_code, reason): self.exit() force_quit(exit_code) - def signal_cleanup(self): + def signal_cleanup(self) -> None: #placeholder for stuff that can be cleaned up from the signal handler #(non UI thread stuff) pass - def disconnect_and_quit(self, exit_code, reason): + def disconnect_and_quit(self, exit_code:int, reason:str) -> None: #make sure that we set the exit code early, #so the protocol shutdown won't set a different one: if self.exit_code is None: @@ -323,7 +324,7 @@ def protocol_closed(): p.send_disconnect([reason], done_callback=protocol_closed) self.timeout_add(1000, self.quit, exit_code) - def exit(self): + def exit(self) -> None: log("XpraClientBase.exit() calling %s", sys.exit) sys.exit() @@ -367,7 +368,7 @@ def setup_connection(self, conn): netlog("setup_connection(%s) protocol=%s", conn, protocol) return protocol - def init_aliases(self): + def init_aliases(self) -> None: i = 1 for key in PACKET_TYPES: self._aliases[i] = key @@ -376,7 +377,7 @@ def init_aliases(self): def has_password(self) -> bool: return self.password or self.password_file or os.environ.get('XPRA_PASSWORD') - def send_hello(self, challenge_response=None, client_salt=None): + def send_hello(self, challenge_response=None, client_salt=None) -> None: if not self._protocol: log("send_hello(..) skipped, no protocol (listen mode?)") return @@ -411,13 +412,13 @@ def send_hello(self, challenge_response=None, client_salt=None): print_nested_dict(hello, print_fn=netlog.info) self.send("hello", hello) - def verify_connected(self): + def verify_connected(self) -> None: if not self.connection_established: #server has not said hello yet self.warn_and_quit(ExitCode.TIMEOUT, "connection timed out") - def make_hello_base(self): + def make_hello_base(self) -> Dict[str,Any]: capabilities = flatten_dict(get_network_caps(FULL_INFO)) #add "kerberos", "gss" and "u2f" digests if enabled: for handler in self.challenge_handlers: @@ -468,7 +469,7 @@ def up(prefix, d): capabilities.update(self.hello_extra) return capabilities - def get_cipher_caps(self): + def get_cipher_caps(self) -> Dict[str,Any]: encryption = self.get_encryption() cryptolog(f"encryption={encryption}") if not encryption: @@ -487,7 +488,7 @@ def get_cipher_caps(self): key_salt = get_salt() iterations = get_iterations() padding = choose_padding(self.server_padding_options) - cipher_caps = { + cipher_caps : Dict[str,Any] = { "" : enc, "mode" : mode, "iv" : iv, @@ -506,17 +507,17 @@ def get_cipher_caps(self): return cipher_caps - def get_version_info(self) -> dict: + def get_version_info(self) -> Dict[str, Any]: return get_version_info(FULL_INFO) - def make_hello(self): + def make_hello(self) -> Dict[str,Any]: return {"aliases" : self.get_network_aliases()} def get_network_aliases(self): return dict((v,k) for k,v in self._aliases.items()) - def compressed_wrapper(self, datatype, data, level=5, **kwargs): + def compressed_wrapper(self, datatype, data, level=5, **kwargs) -> compression.Compressed: if level>0 and len(data)>=256: kw = {} #brotli is not enabled by default as a generic compressor @@ -535,15 +536,15 @@ def compressed_wrapper(self, datatype, data, level=5, **kwargs): return compression.Compressed(f"raw {datatype}", data, can_inline=True) - def send(self, *parts): + def send(self, *parts) -> None: self._ordinary_packets.append(parts) self.have_more() - def send_now(self, *parts): + def send_now(self, *parts) -> None: self._priority_packets.append(parts) self.have_more() - def send_positional(self, packet): + def send_positional(self, packet) -> None: #packets that include the mouse position in them #we can cancel the pending position packets self._ordinary_packets.append(packet) @@ -552,7 +553,7 @@ def send_positional(self, packet): self.cancel_send_mouse_position_timer() self.have_more() - def next_pointer_sequence(self, device_id): + def next_pointer_sequence(self, device_id:int) -> int: if device_id<0: #unspecified device, don't bother with sequence numbers return 0 @@ -560,7 +561,7 @@ def next_pointer_sequence(self, device_id): self._pointer_sequence[device_id] = seq return seq - def send_mouse_position(self, device_id, wid, pos, modifiers=None, buttons=None, props=None): + def send_mouse_position(self, device_id, wid, pos, modifiers=None, buttons=None, props=None) -> None: if "pointer" in self.server_packet_types: #v5 packet type, most attributes are optional: attrs = props or {} @@ -588,14 +589,14 @@ def send_mouse_position(self, device_id, wid, pos, modifiers=None, buttons=None, else: self.do_send_mouse_position() - def do_send_mouse_position(self): + def do_send_mouse_position(self) -> None: self._mouse_position_timer = 0 self._mouse_position_send_time = monotonic() self._mouse_position = self._mouse_position_pending mouselog("do_send_mouse_position() position=%s", self._mouse_position) self.have_more() - def cancel_send_mouse_position_timer(self): + def cancel_send_mouse_position_timer(self) -> None: mpt = self._mouse_position_timer if mpt: self._mouse_position_timer = 0 @@ -622,7 +623,7 @@ def next_packet(self): return packet, None, None, None, synchronous, has_more - def stop_progress_process(self): + def stop_progress_process(self) -> None: pp = self.progress_process if not pp: return @@ -634,7 +635,7 @@ def stop_progress_process(self): except Exception: pass - def cleanup(self): + def cleanup(self) -> None: self.cancel_progress_timer() self.stop_progress_process() reaper_cleanup() @@ -653,32 +654,32 @@ def cleanup(self): dump_all_frames() - def glib_init(self): + def glib_init(self) -> None: #this will take care of calling threads_init if needed: from gi.repository import GLib # @UnresolvedImport register_SIGUSR_signals(GLib.idle_add) - def run(self): + def run(self) -> None: self.start_protocol() - def start_protocol(self): + def start_protocol(self) -> None: #protocol may be None in "listen" mode if self._protocol: self._protocol.start() - def quit(self, exit_code=0): + def quit(self, exit_code:int=0) -> None: raise NotImplementedError() - def warn_and_quit(self, exit_code, message): + def warn_and_quit(self, exit_code:int, message:str): log.warn(message) self.quit(exit_code) - def send_shutdown_server(self): + def send_shutdown_server(self) -> None: assert self.server_client_shutdown self.send("shutdown-server") - def _process_disconnect(self, packet): + def _process_disconnect(self, packet) -> None: #ie: ("disconnect", "version error", "incompatible version") netlog("%s", packet) info = tuple(nonl(bytestostr(x)) for x in packet[1:]) @@ -694,7 +695,7 @@ def _process_disconnect(self, packet): #tell the user why the server is disconnecting us self.server_disconnect(*info) - def server_disconnect_warning(self, reason, *extra_info): + def server_disconnect_warning(self, reason:str, *extra_info) -> None: log.warn("Warning: server connection failure:") log.warn(f" {reason}") for x in extra_info: @@ -706,10 +707,10 @@ def server_disconnect_warning(self, reason, *extra_info): else: self.quit(ExitCode.FAILURE) - def server_disconnect(self, reason, *extra_info): + def server_disconnect(self, reason:str, *extra_info) -> None: self.quit(self.server_disconnect_exit_code(reason, *extra_info)) - def server_disconnect_exit_code(self, reason, *extra_info): + def server_disconnect_exit_code(self, reason:str, *extra_info) -> None: if self.exit_code is None and (LOG_DISCONNECT or disconnect_is_an_error(reason)): l = log.info else: @@ -725,7 +726,7 @@ def server_disconnect_exit_code(self, reason, *extra_info): return ExitCode.OK - def _process_connection_lost(self, _packet): + def _process_connection_lost(self, _packet) -> None: p = self._protocol if p and p.input_raw_packetcount==0: props = p.get_info() @@ -748,13 +749,13 @@ def _process_connection_lost(self, _packet): ######################################## # Authentication - def _process_challenge(self, packet): + def _process_challenge(self, packet) -> None: authlog(f"processing challenge: {packet[1:]}") if not self.validate_challenge_packet(packet): return start_thread(self.do_process_challenge, "call-challenge-handlers", True, (packet, )) - def do_process_challenge(self, packet): + def do_process_challenge(self, packet) -> None: digest = bytestostr(packet[3]) authlog(f"challenge handlers: {self.challenge_handlers}, digest: {digest}") while self.challenge_handlers: @@ -973,10 +974,10 @@ def fail(msg): return True - def get_encryption(self): + def get_encryption(self) -> str: p = self._protocol if not p: - return None + return "" conn = p._conn #prefer the socket option, fallback to "--encryption=" option: encryption = conn.options.get("encryption", self.encryption) @@ -990,7 +991,7 @@ def get_encryption(self): cryptolog("found encryption key environment variable, enabling {encryption!r} encryption") return encryption - def get_encryption_key(self): + def get_encryption_key(self) -> bytes: conn = self._protocol._conn keydata = parse_encoded_bin_data(conn.options.get("keydata", None)) cryptolog(f"get_encryption_key() connection options keydata={ellipsizer(keydata)}") @@ -1001,23 +1002,23 @@ def get_encryption_key(self): if not os.path.isabs(keyfile): keyfile = os.path.abspath(keyfile) if os.path.exists(keyfile): - key = filedata_nocrlf(keyfile) - if key: + keydata = filedata_nocrlf(keyfile) + if keydata: cryptolog("get_encryption_key() loaded %i bytes from '%s'", - len(key or ""), keyfile) - return key + len(keydata or b""), keyfile) + return keydata cryptolog(f"get_encryption_key() keyfile {keyfile!r} is empty") else: cryptolog(f"get_encryption_key() file {keyfile!r} does not exist") XPRA_ENCRYPTION_KEY = "XPRA_ENCRYPTION_KEY" - key = strtobytes(os.environ.get(XPRA_ENCRYPTION_KEY, '')) + keydata = strtobytes(os.environ.get(XPRA_ENCRYPTION_KEY, '')) cryptolog(f"get_encryption_key() got %i bytes from {XPRA_ENCRYPTION_KEY!r} environment variable", - len(key or "")) - if key: - return key.strip(b"\n\r") + len(keydata or "")) + if keydata: + return keydata.strip(b"\n\r") raise InitExit(ExitCode.ENCRYPTION, "no encryption key") - def _process_hello(self, packet): + def _process_hello(self, packet) -> None: if LOG_HELLO: netlog.info("received hello:") print_nested_dict(packet[1], print_fn=netlog.info) @@ -1091,17 +1092,17 @@ def parse_encryption_capabilities(self, caps : typedict) -> bool: return False return True - def _process_set_deflate(self, packet): + def _process_set_deflate(self, packet) -> None: #legacy, should not be used for anything pass - def _process_startup_complete(self, packet): + def _process_startup_complete(self, packet) -> None: #can be received if we connect with "xpra stop" or other command line client #as the server is starting up self.completed_startup = packet - def _process_gibberish(self, packet): + def _process_gibberish(self, packet) -> None: log("process_gibberish(%s)", ellipsizer(packet)) message, data = packet[1:3] from xpra.net.socket_util import guess_packet_type #pylint: disable=import-outside-toplevel @@ -1139,7 +1140,7 @@ def _process_gibberish(self, packet): netlog.error(f" packet no {pcount} data: {repr_ellipsized(data)}") self.quit(exit_code) - def _process_invalid(self, packet): + def _process_invalid(self, packet) -> None: message, data = packet[1:3] netlog.info(f"Received invalid packet: {message}") netlog(" data: %s", ellipsizer(data)) @@ -1152,12 +1153,12 @@ def _process_invalid(self, packet): ###################################################################### # packets: - def remove_packet_handlers(self, *keys): + def remove_packet_handlers(self, *keys) -> None: for k in keys: for d in (self._packet_handlers, self._ui_packet_handlers): d.pop(k, None) - def init_packet_handlers(self): + def init_packet_handlers(self) -> None: self._packet_handlers = {} self._ui_packet_handlers = {} self.add_packet_handler("hello", self._process_hello, False) @@ -1171,14 +1172,14 @@ def init_packet_handlers(self): INVALID: self._process_invalid, }) - def init_authenticated_packet_handlers(self): + def init_authenticated_packet_handlers(self) -> None: FilePrintMixin.init_authenticated_packet_handlers(self) - def add_packet_handlers(self, defs, main_thread=True): + def add_packet_handlers(self, defs, main_thread:bool=True) -> None: for packet_type, handler in defs.items(): self.add_packet_handler(packet_type, handler, main_thread) - def add_packet_handler(self, packet_type, handler, main_thread=True): + def add_packet_handler(self, packet_type:str, handler:Callable, main_thread:bool=True) -> None: netlog("add_packet_handler%s", (packet_type, handler, main_thread)) self.remove_packet_handlers(packet_type) if main_thread: diff --git a/xpra/client/base/fileprint_mixin.py b/xpra/client/base/fileprint_mixin.py index f267c0e716..c90ed27a3d 100644 --- a/xpra/client/base/fileprint_mixin.py +++ b/xpra/client/base/fileprint_mixin.py @@ -1,8 +1,10 @@ # This file is part of Xpra. -# Copyright (C) 2010-2021 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. +from typing import Dict, Any + from xpra.util import envbool, envint, csv, typedict from xpra.net.file_transfer import FileTransferHandler from xpra.client.base.stub_client_mixin import StubClientMixin @@ -23,15 +25,15 @@ def __init__(self): StubClientMixin.__init__(self) FileTransferHandler.__init__(self) self.printer_attributes = [] - self.send_printers_timer = 0 + self.send_printers_timer : int = 0 self.exported_printers = None - self.remote_request_file = False + self.remote_request_file : bool = False - def init(self, opts): + def init(self, opts) -> None: #printing and file transfer: FileTransferHandler.init_opts(self, opts) - def init_authenticated_packet_handlers(self): + def init_authenticated_packet_handlers(self) -> None: for packet_type, handler in { "open-url" : self._process_open_url, "send-file" : self._process_send_file, @@ -42,10 +44,10 @@ def init_authenticated_packet_handlers(self): }.items(): self.add_packet_handler(packet_type, handler, False) - def get_caps(self) -> dict: + def get_caps(self) -> Dict[str,Any]: return self.get_file_transfer_features() - def cleanup(self): + def cleanup(self) -> None: #we must clean printing before FileTransferHandler, which turns the printing flag off! self.cleanup_printing() FileTransferHandler.cleanup(self) @@ -56,7 +58,7 @@ def parse_server_capabilities(self, c : typedict) -> bool: self.remote_request_file = c.boolget("request-file", False) return True - def parse_printing_capabilities(self, caps : typedict): + def parse_printing_capabilities(self, caps : typedict) -> None: printlog("parse_printing_capabilities() client printing support=%s", self.printing) if self.printing: server_printing = caps.boolget("printing") @@ -67,7 +69,7 @@ def parse_printing_capabilities(self, caps : typedict): self.timeout_add(INIT_PRINTING_DELAY*1000, self.init_printing) - def init_printing(self): + def init_printing(self) -> None: try: from xpra.platform.printing import init_printing # pylint: disable=import-outside-toplevel printlog("init_printing=%s", init_printing) @@ -80,7 +82,7 @@ def init_printing(self): self.send_printers() printlog("init_printing() enabled=%s", self.printing) - def cleanup_printing(self): + def cleanup_printing(self) -> None: printlog("cleanup_printing() printing=%s", self.printing) if not self.printing: return @@ -96,7 +98,7 @@ def cleanup_printing(self): printlog.warn("Warning: failed to cleanup printing subsystem:") printlog.warn(" %s", e) - def send_printers(self, *args): + def send_printers(self, *args) -> None: printlog("send_printers%s timer=%s", args, self.send_printers_timer) #dbus can fire dozens of times for a single printer change #so we wait a bit and fire via a timer to try to batch things together: @@ -104,18 +106,18 @@ def send_printers(self, *args): return self.send_printers_timer = self.timeout_add(500, self.do_send_printers) - def cancel_send_printers_timer(self): + def cancel_send_printers_timer(self) -> None: spt = self.send_printers_timer printlog("cancel_send_printers_timer() send_printers_timer=%s", spt) if spt: - self.send_printers_timer = None + self.send_printers_timer = 0 self.source_remove(spt) - def do_send_printers(self): - self.send_printers_timer = None + def do_send_printers(self) -> None: + self.send_printers_timer = 0 start_thread(self.send_printers_thread, "send-printers", True) - def send_printers_thread(self): + def send_printers_thread(self) -> None: from xpra.platform.printing import get_printers, get_mimetypes # pylint: disable=import-outside-toplevel try: printers = get_printers() diff --git a/xpra/client/base/stub_client_mixin.py b/xpra/client/base/stub_client_mixin.py index 2c76c91565..bf98231bc4 100644 --- a/xpra/client/base/stub_client_mixin.py +++ b/xpra/client/base/stub_client_mixin.py @@ -5,7 +5,7 @@ import sys import time -from typing import Callable, List +from typing import Callable, List, Dict, Any from xpra.util import typedict from xpra.net.compression import Compressed @@ -64,13 +64,13 @@ def setup_connection(self, _conn) -> None: Prepare to run using this connection to the server. """ - def get_caps(self) -> dict: + def get_caps(self) -> Dict[str,Any]: """ Return the capabilities provided by this mixin. """ return {} - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: """ Information contained in this mixin """ diff --git a/xpra/client/gl/gl_check.py b/xpra/client/gl/gl_check.py index 66127b8128..f864ce2c9f 100755 --- a/xpra/client/gl/gl_check.py +++ b/xpra/client/gl/gl_check.py @@ -7,7 +7,7 @@ import sys import logging -from typing import Any, Tuple +from typing import Any, Tuple, Dict from xpra.util import envbool, envint, csv from xpra.os_util import bytestostr @@ -85,7 +85,7 @@ def get_max_texture_size() -> int: return min(rect_texture_size, texture_size) -def check_PyOpenGL_support(force_enable) -> dict[str,Any]: +def check_PyOpenGL_support(force_enable) -> Dict[str,Any]: props : dict[str,Any] = { "platform" : sys.platform, } diff --git a/xpra/client/gl/gl_window_backing_base.py b/xpra/client/gl/gl_window_backing_base.py index 97398b65bd..738e1338c6 100644 --- a/xpra/client/gl/gl_window_backing_base.py +++ b/xpra/client/gl/gl_window_backing_base.py @@ -184,15 +184,20 @@ if OPENGL_DEBUG: try: # pylint: disable=ungrouped-imports + from OpenGL.GL.KHR import debug as KHR_debug + GL_DEBUG_OUTPUT = int(KHR_debug.GL_DEBUG_OUTPUT) # @UndefinedVariable + GL_DEBUG_OUTPUT_SYNCHRONOUS = int(KHR_debug.GL_DEBUG_OUTPUT_SYNCHRONOUS) from OpenGL.GL.KHR.debug import ( - GL_DEBUG_OUTPUT, GL_DEBUG_OUTPUT_SYNCHRONOUS, glDebugMessageControl, glDebugMessageCallback, glInitDebugKHR, ) except ImportError: log("Unable to import GL_KHR_debug OpenGL extension. Debug output will be more limited.") try: - from OpenGL.GL.GREMEDY.string_marker import glInitStringMarkerGREMEDY, glStringMarkerGREMEDY - from OpenGL.GL.GREMEDY.frame_terminator import glInitFrameTerminatorGREMEDY, glFrameTerminatorGREMEDY + from OpenGL.GL.GREMEDY import string_marker, frame_terminator + glInitStringMarkerGREMEDY = string_marker.glInitStringMarkerGREMEDY + glStringMarkerGREMEDY = string_marker.glStringMarkerGREMEDY + glInitFrameTerminatorGREMEDY = frame_terminator.glInitFrameTerminatorGREMEDY + glFrameTerminatorGREMEDY = frame_terminator.glFrameTerminatorGREMEDY from OpenGL.GL import GLDEBUGPROC #@UnresolvedImport def py_gl_debug_callback(source, error_type, error_id, severity, length, message, param): log.error("src %x type %x id %x severity %x length %d message %s, param=%s", diff --git a/xpra/client/gtk_base/gtk_client_base.py b/xpra/client/gtk_base/gtk_client_base.py index 77899c19d9..5c17d7d89c 100644 --- a/xpra/client/gtk_base/gtk_client_base.py +++ b/xpra/client/gtk_base/gtk_client_base.py @@ -1,6 +1,6 @@ # This file is part of Xpra. # Copyright (C) 2011 Serviware (Arthur Huillet, ) -# Copyright (C) 2010-2022 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Copyright (C) 2008, 2010 Nathaniel Smith # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -10,6 +10,7 @@ from time import monotonic from subprocess import Popen, PIPE from threading import Event +from typing import Dict, Any from gi.repository import Gtk, Gdk, GdkPixbuf # @UnresolvedImport from xpra.client.gtk_base.gtk_client_window_base import HAS_X11_BINDINGS, XSHAPE @@ -844,7 +845,7 @@ def get_current_modifiers(self): return self.mask_to_names(modifiers_mask) - def make_hello(self) -> dict: + def make_hello(self) -> Dict[str,Any]: capabilities = UIXpraClient.make_hello(self) capabilities["named_cursors"] = len(cursor_types)>0 capabilities["encoding.transparency"] = self.has_transparency() diff --git a/xpra/client/gui/ui_client_base.py b/xpra/client/gui/ui_client_base.py index 1626beb733..9ac01d1631 100644 --- a/xpra/client/gui/ui_client_base.py +++ b/xpra/client/gui/ui_client_base.py @@ -1,12 +1,13 @@ # This file is part of Xpra. # Copyright (C) 2011 Serviware (Arthur Huillet, ) -# Copyright (C) 2010-2021 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Copyright (C) 2008, 2010 Nathaniel Smith # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import os import sys +from typing import Type, Dict, List, Any, Callable from xpra.client.base.client_base import XpraClientBase from xpra.client.gui.keyboard_helper import KeyboardHelper, add_xkbmap_legacy_prefix @@ -76,7 +77,7 @@ CLIENT_BASES.append(TrayClient) CLIENT_BASES = tuple(CLIENT_BASES) -ClientBaseClass = type('ClientBaseClass', CLIENT_BASES, {}) +ClientBaseClass : Type = type('ClientBaseClass', CLIENT_BASES, {}) log = Logger("client") keylog = Logger("client", "keyboard") @@ -106,7 +107,7 @@ def __init__(self): # pylint: disable=super-init-not-called log.info(f"Xpra {self.client_toolkit()} client version {full_version_str()}") #mmap_enabled belongs in the MmapClient mixin, #but it is used outside it, so make sure we define it: - self.mmap_enabled = False + self.mmap_enabled : bool = False #same for tray: self.tray = None for c in CLIENT_BASES: @@ -122,53 +123,53 @@ def __init__(self): # pylint: disable=super-init-not-called if wm: log.info(f" window manager is {wm!r}") - self._ui_events = 0 - self.title = "" - self.session_name = "" + self._ui_events : int = 0 + self.title : str = "" + self.session_name : str = "" - self.server_platform = "" - self.server_session_name = None + self.server_platform : str = "" + self.server_session_name : str = "" #features: - self.opengl_enabled = False - self.opengl_props = {} - self.readonly = False - self.xsettings_enabled = False - self.server_start_new_commands = False + self.opengl_enabled : bool = False + self.opengl_props : Dict[str,Any] = {} + self.readonly : bool = False + self.xsettings_enabled : bool = False + self.server_start_new_commands : bool = False self.server_xdg_menu = None - self.start_new_commands = False + self.start_new_commands : bool = False self.request_start = [] self.request_start_child = [] self.headerbar = None #in WindowClient - should it be? #self.server_is_desktop = False - self.server_sharing = False - self.server_sharing_toggle = False - self.server_lock = False - self.server_lock_toggle = False - self.server_keyboard = True - self.server_pointer = True + self.server_sharing : bool = False + self.server_sharing_toggle : bool = False + self.server_lock : bool = False + self.server_lock_toggle : bool = False + self.server_keyboard : bool = True + self.server_pointer : bool = True - self.client_supports_opengl = False - self.client_supports_sharing = False - self.client_lock = False + self.client_supports_opengl : bool = False + self.client_supports_sharing : bool = False + self.client_lock : bool = False #helpers and associated flags: self.client_extras = None - self.keyboard_helper_class = KeyboardHelper + self.keyboard_helper_class : Type = KeyboardHelper self.keyboard_helper = None - self.keyboard_grabbed = False - self.keyboard_sync = False - self.kh_warning = False + self.keyboard_grabbed : bool = False + self.keyboard_sync : bool = False + self.kh_warning : bool = False self.menu_helper = None #state: - self._on_handshake = [] - self._on_server_setting_changed = {} + self._on_handshake : List[Callable] = [] + self._on_server_setting_changed : Dict[str,Callable] = {} - def init(self, opts): + def init(self, opts) -> None: """ initialize variables from configuration """ self.init_aliases() for c in CLIENT_BASES: @@ -237,23 +238,23 @@ def send_keyboard(*parts): except Exception: log("failed to calculate automatic delay", exc_info=True) - def get_vrefresh(self): + def get_vrefresh(self) -> int: #this method is overridden in the GTK client from xpra.platform.gui import get_vrefresh #pylint: disable=import-outside-toplevel return get_vrefresh() - def run(self): + def run(self) -> None: if self.client_extras: self.idle_add(self.client_extras.ready) for c in CLIENT_BASES: c.run(self) - def quit(self, exit_code=0): + def quit(self, exit_code:int=0) -> None: raise NotImplementedError() - def cleanup(self): + def cleanup(self) -> None: log("UIXpraClient.cleanup()") for c in CLIENT_BASES: c.cleanup(self) @@ -271,15 +272,15 @@ def cleanup(self): log("UIXpraClient.cleanup() done") - def signal_cleanup(self): + def signal_cleanup(self) -> None: log("UIXpraClient.signal_cleanup()") XpraClientBase.signal_cleanup(self) reaper_cleanup() log("UIXpraClient.signal_cleanup() done") - def get_info(self): - info = {} + def get_info(self) -> Dict[str,Any]: + info : Dict[str,Any] = {} if FULL_INFO>0: info.update({ "pid" : os.getpid(), @@ -300,23 +301,23 @@ def get_info(self): return info - def show_about(self, *_args): + def show_about(self, *_args) -> None: log.warn(f"show_about() is not implemented in {self!r}") - def show_session_info(self, *_args): + def show_session_info(self, *_args) -> None: log.warn(f"show_session_info() is not implemented in {self!r}") - def show_bug_report(self, *_args): + def show_bug_report(self, *_args) -> None: log.warn(f"show_bug_report() is not implemented in {self!r}") - def init_opengl(self, _enable_opengl): + def init_opengl(self, _enable_opengl) -> None: self.opengl_enabled = False self.client_supports_opengl = False self.opengl_props = {"info" : "not supported"} - def _ui_event(self): + def _ui_event(self) -> None: if self._ui_events==0: self.emit("first-ui-received") self._ui_events += 1 @@ -329,7 +330,7 @@ def get_current_modifiers(self): raise NotImplementedError() - def send_start_new_commands(self): + def send_start_new_commands(self) -> None: log(f"send_start_new_commands() request_start={self.request_start}, request_start_child={self.request_start_child}") import shlex for cmd in self.request_start: @@ -339,7 +340,7 @@ def send_start_new_commands(self): cmd_parts = shlex.split(cmd) self.send_start_command(cmd_parts[0], cmd, False) - def send_start_command(self, name, command, ignore, sharing=True): + def send_start_command(self, name:str, command:List[str], ignore:bool, sharing:bool=True) -> None: log("send_start_command%s", (name, command, ignore, sharing)) assert name is not None and command is not None and ignore is not None self.send("start-command", name, command, ignore, sharing) @@ -369,7 +370,7 @@ def server_disconnect_warning(self, reason, *info): self.timeout_add(delay*1000, XpraClientBase.server_disconnect_warning, self, reason, *info) self.cleanup() - def server_disconnect(self, reason, *info): + def server_disconnect(self, reason:str, *info) -> None: body = "\n".join(info) self.may_notify(NotificationID.DISCONNECT, f"Xpra Session Disconnected: {reason}", body, icon_name="disconnected") delay = NOTIFICATION_EXIT_DELAY*mixin_features.notifications diff --git a/xpra/client/mixins/display.py b/xpra/client/mixins/display.py index c33b3e6c17..52e17b7cf2 100644 --- a/xpra/client/mixins/display.py +++ b/xpra/client/mixins/display.py @@ -1,9 +1,10 @@ # This file is part of Xpra. -# Copyright (C) 2010-2022 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. from time import monotonic +from typing import Dict, Any, Tuple from xpra.exit_codes import ExitCode from xpra.platform.features import REINIT_WINDOWS @@ -105,7 +106,7 @@ def get_info(self): ###################################################################### # hello: - def get_caps(self) -> dict: + def get_caps(self) -> Dict[str,Any]: caps = { "randr_notify" : True, "show-desktop" : True, @@ -154,7 +155,7 @@ def get_caps(self) -> dict: })) return caps - def get_dpi_caps(self) -> dict: + def get_dpi_caps(self) -> Dict[str,Any]: #command line (or config file) override supplied: caps = {} dpi = 0 @@ -180,7 +181,7 @@ def get_dpi_caps(self) -> dict: log("get_dpi_caps()=%s", caps) return caps - def get_scaling_caps(self) -> dict: + def get_scaling_caps(self) -> Dict[str,Any]: return { "" : True, "enabled" : self.xscale!=1 or self.yscale!=1, @@ -190,7 +191,7 @@ def get_scaling_caps(self) -> dict: def get_vrefresh(self): return get_vrefresh() - def get_screen_caps(self) -> dict: + def get_screen_caps(self) -> Dict[str,Any]: caps = { "vrefresh" : self.get_vrefresh(), "cursor" : { @@ -246,7 +247,7 @@ def parse_server_capabilities(self, c : typedict) -> bool: self.server_multi_monitors, self.server_monitors) return True - def process_ui_capabilities(self, c : typedict): + def process_ui_capabilities(self, c : typedict) -> None: self.server_is_desktop = c.boolget("shadow") or c.boolget("desktop") or c.boolget("monitor") log("process_ui_capabilities(%s) desktop=%s, monitor=%s", c, c.boolget("desktop"), c.boolget("monitor")) if not c.boolget("monitor"): @@ -280,7 +281,7 @@ def process_ui_capabilities(self, c : typedict): self.set_max_packet_size() self.send_icc_data() - def send_icc_data(self): + def send_icc_data(self) -> None: if SYNC_ICC and "configure-display" in self.server_packet_types: #it is now safe to send the colourspace data if we have any: icc = self.get_icc_info() @@ -293,7 +294,7 @@ def send_icc_data(self): } }) - def set_max_packet_size(self): + def set_max_packet_size(self) -> None: p = self._protocol if not p or p.TYPE!="xpra": return @@ -324,21 +325,21 @@ def set_max_packet_size(self): def has_transparency(self) -> bool: return False - def get_icc_info(self) -> dict: + def get_icc_info(self) -> Dict[str,Any]: return get_icc_info() - def get_display_icc_info(self) -> dict: + def get_display_icc_info(self) -> Dict[str,Any]: return get_display_icc_info() def get_monitors_info(self): return {} - def _process_show_desktop(self, packet): + def _process_show_desktop(self, packet) -> None: show = packet[1] log("calling %s(%s)", show_desktop, show) show_desktop(show) - def _process_desktop_size(self, packet): + def _process_desktop_size(self, packet) -> None: root_w, root_h, max_w, max_h = packet[1:5] log("server has resized the desktop to: %sx%s (max %sx%s)", root_w, root_h, max_w, max_h) self.server_max_desktop_size = max_w, max_h @@ -347,7 +348,7 @@ def _process_desktop_size(self, packet): self.may_adjust_scaling() - def may_adjust_scaling(self): + def may_adjust_scaling(self) -> None: log("may_adjust_scaling() server_is_desktop=%s, desktop_fullscreen=%s", self.server_is_desktop, self.desktop_fullscreen) if self.server_is_desktop and not self.desktop_fullscreen: @@ -406,10 +407,10 @@ def mint(v): ###################################################################### # screen scaling: - def fsx(self, v): + def fsx(self, v) -> float: """ convert X coordinate from server to client """ return v*self.xscale - def fsy(self, v): + def fsy(self, v) -> float: """ convert Y coordinate from server to client """ return v*self.yscale def sx(self, v) -> int: @@ -418,10 +419,10 @@ def sx(self, v) -> int: def sy(self, v) -> int: """ convert Y coordinate from server to client """ return round(self.fsy(v)) - def srect(self, x, y, w, h): + def srect(self, x, y, w, h) -> Tuple[int, int, int, int]: """ convert rectangle coordinates from server to client """ return self.sx(x), self.sy(y), self.sx(w), self.sy(h) - def sp(self, x, y): + def sp(self, x, y) -> Tuple[float, float]: """ convert X,Y coordinates from server to client """ return self.sx(x), self.sy(y) @@ -431,26 +432,26 @@ def cx(self, v) -> int: def cy(self, v) -> int: """ convert Y coordinate from client to server """ return round(v/self.yscale) - def crect(self, x, y, w, h): + def crect(self, x, y, w, h) -> Tuple[int, int, int, int]: """ convert rectangle coordinates from client to server """ return self.cx(x), self.cy(y), self.cx(w), self.cy(h) - def cp(self, x, y): + def cp(self, x, y) -> Tuple[int, int]: """ convert X,Y coordinates from client to server """ return self.cx(x), self.cy(y) ###################################################################### # desktop, screen and scaling: - def desktops_changed(self, *args): + def desktops_changed(self, *args) -> None: workspacelog("desktops_changed%s", args) self.screen_size_changed(*args) - def workspace_changed(self, *args): + def workspace_changed(self, *args) -> None: workspacelog("workspace_changed%s", args) for win in self._id_to_window.values(): win.workspace_changed() - def screen_size_changed(self, *args): + def screen_size_changed(self, *args) -> None: log("screen_size_changed(%s) timer=%s", args, self.screen_size_change_timer) if self.screen_size_change_timer: return @@ -478,7 +479,7 @@ def do_process_screen_size_change(self): self.reinit_window_icons() - def get_screen_settings(self): + def get_screen_settings(self) -> Tuple: u_root_w, u_root_h = self.get_root_size() root_w, root_h = self.cp(u_root_w, u_root_h) self._current_screen_sizes = self.get_screen_sizes() @@ -506,7 +507,7 @@ def get_screen_settings(self): monitors = self.get_monitors_info() return (root_w, root_h, sss, ndesktops, desktop_names, u_root_w, u_root_h, xdpi, ydpi, rrate, monitors) - def update_screen_size(self): + def update_screen_size(self) -> None: self.screen_size_change_timer = None screen_settings = self.get_screen_settings() log("update_screen_size() new settings=%s", screen_settings) @@ -560,37 +561,37 @@ def get_ydpi(self) -> int: return get_ydpi() - def scaleup(self): + def scaleup(self) -> None: scaling = max(self.xscale, self.yscale) options = scaleup_value(scaling) scalinglog("scaleup() options=%s", options) if options: self._scaleto(min(options)) - def scaledown(self): + def scaledown(self) -> None: scaling = min(self.xscale, self.yscale) options = scaledown_value(scaling) scalinglog("scaledown() options=%s", options) if options: self._scaleto(max(options)) - def _scaleto(self, new_scaling): + def _scaleto(self, new_scaling) -> None: scaling = max(self.xscale, self.yscale) scalinglog("_scaleto(%s) current value=%s", r4cmp(new_scaling, 1000)/1000.0, r4cmp(scaling, 1000)/1000.0) if new_scaling>0: self.scale_change(new_scaling/scaling, new_scaling/scaling) - def scalingoff(self): + def scalingoff(self) -> None: self.scaleset(1, 1) - def scalereset(self): + def scalereset(self) -> None: self.scaleset(*self.initial_scaling) - def scaleset(self, xscale=1, yscale=1): + def scaleset(self, xscale=1, yscale=1) -> None: scalinglog("scaleset(%s, %s) current scaling: %s, %s", xscale, yscale, self.xscale, self.yscale) self.scale_change(xscale/self.xscale, yscale/self.yscale) - def scale_change(self, xchange=1, ychange=1): + def scale_change(self, xchange=1, ychange=1) -> None: scalinglog("scale_change(%s, %s)", xchange, ychange) if self.server_is_desktop and self.desktop_fullscreen: scalinglog("scale_change(%s, %s) ignored, fullscreen shadow mode is active", xchange, ychange) @@ -642,7 +643,7 @@ def clamp(v): scalinglog("scale_change new scaling: %sx%s, change: %sx%s", self.xscale, self.yscale, xchange, ychange) self.scale_reinit(xchange, ychange) - def scale_reinit(self, xchange=1.0, ychange=1.0): + def scale_reinit(self, xchange=1.0, ychange=1.0) -> None: #wait at least one second before changing again: self.scale_change_embargo = monotonic()+SCALING_EMBARGO_TIME if fequ(self.xscale, self.yscale): @@ -666,6 +667,6 @@ def new_size_fn(w, h): self.emit("scaling-changed") - def init_authenticated_packet_handlers(self): + def init_authenticated_packet_handlers(self) -> None: self.add_packet_handler("show-desktop", self._process_show_desktop) self.add_packet_handler("desktop_size", self._process_desktop_size) diff --git a/xpra/client/mixins/encodings.py b/xpra/client/mixins/encodings.py index f105de4ab7..6dd68992a5 100644 --- a/xpra/client/mixins/encodings.py +++ b/xpra/client/mixins/encodings.py @@ -5,6 +5,7 @@ # later version. See the file COPYING for details. import os +from typing import Dict, Any from xpra.codecs.codec_constants import preforder from xpra.codecs.loader import load_codec, codec_versions, has_codec, get_codec @@ -150,7 +151,7 @@ def get_info(self): } - def get_caps(self) -> dict: + def get_caps(self) -> Dict[str,Any]: caps = { "encodings" : self.get_encodings(), "encodings.core" : self.get_core_encodings(), @@ -183,7 +184,7 @@ def _parse_server_capabilities(self, c): self.encoding = e - def get_batch_caps(self) -> dict: + def get_batch_caps(self) -> Dict[str,Any]: #batch options: caps = {} for bprop in ("always", "min_delay", "max_delay", "delay", "max_events", "max_pixels", "time_unit"): @@ -196,7 +197,7 @@ def get_batch_caps(self) -> dict: log("get_batch_caps()=%s", caps) return caps - def get_encodings_caps(self) -> dict: + def get_encodings_caps(self) -> Dict[str,Any]: if B_FRAMES: video_b_frames = ("h264", ) #only tested with dec_avcodec2 else: diff --git a/xpra/client/mixins/network_listener.py b/xpra/client/mixins/network_listener.py index cc30a2903c..0a7503e33d 100644 --- a/xpra/client/mixins/network_listener.py +++ b/xpra/client/mixins/network_listener.py @@ -1,11 +1,12 @@ # This file is part of Xpra. -# Copyright (C) 2022 Antoine Martin +# Copyright (C) 2022-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. #pylint: disable-msg=E1101 import os import sys +from typing import Dict, Any from xpra.version_util import version_str from xpra.util import envint, envfloat, envbool, typedict, ConnectionMessage @@ -45,7 +46,7 @@ def __init__(self): self._close_timers = {} - def init(self, opts): + def init(self, opts) -> None: def err(msg): raise InitException(msg) self.sockets = create_sockets(opts, err) @@ -63,14 +64,14 @@ def err(msg): else: self.sockets.update(local_sockets) - def run(self): + def run(self) -> None: self.start_listen_sockets() - def cleanup(self): + def cleanup(self) -> None: self.cleanup_sockets() - def cleanup_sockets(self): + def cleanup_sockets(self) -> None: ct = dict(self._close_timers) self._close_timers = {} for proto, tid in ct.items(): @@ -95,7 +96,7 @@ def cleanup_sockets(self): log.error("Error during socket cleanup", exc_info=True) - def start_listen_sockets(self): + def start_listen_sockets(self) -> None: for sock_def, options in self.sockets.items(): socktype, sock, info, _ = sock_def log("start_listen_sockets() will add %s socket %s (%s)", socktype, sock, info) @@ -103,14 +104,14 @@ def start_listen_sockets(self): self.socket_options[sock] = options self.idle_add(self.add_listen_socket, socktype, sock, options) - def add_listen_socket(self, socktype, sock, options): + def add_listen_socket(self, socktype:str, sock, options) -> None: info = self.socket_info.get(sock) log("add_listen_socket(%s, %s, %s) info=%s", socktype, sock, options, info) cleanup = add_listen_socket(socktype, sock, info, None, self._new_connection, options) if cleanup: self.socket_cleanup.append(cleanup) - def _new_connection(self, socktype, listener, handle=0): + def _new_connection(self, socktype:str, listener, handle:int=0) -> bool: """ Accept the new connection, verify that there aren't too many, @@ -126,7 +127,7 @@ def _new_connection(self, socktype, listener, handle=0): log.error("Error handling new connection", exc_info=True) return self.exit_code is None - def handle_new_connection(self, socktype, listener, handle): + def handle_new_connection(self, socktype, listener, handle) -> None: assert socktype, "cannot find socket type for %s" % listener socket_options = self.socket_options.get(listener, {}) if socktype=="named-pipe": @@ -154,7 +155,7 @@ def handle_new_connection(self, socktype, listener, handle): log_new_connection(conn, socket_info) self.make_protocol(socktype, conn, listener) - def make_protocol(self, socktype, conn, listener): + def make_protocol(self, socktype, conn, listener) -> SocketProtocol: socktype = socktype.lower() protocol = SocketProtocol(self, conn, self.process_network_packet) #protocol.large_packets.append(b"info-response") @@ -164,7 +165,7 @@ def make_protocol(self, socktype, conn, listener): protocol.start() #self.schedule_verify_connection_accepted(protocol, self._accept_timeout) - def process_network_packet(self, proto, packet): + def process_network_packet(self, proto, packet) -> None: log("process_network_packet: %s", packet) packet_type = bytestostr(packet[0]) def close(): @@ -242,7 +243,7 @@ def process_control(): tid = self.timeout_add(REQUEST_TIMEOUT*1000, close) self._close_timers[proto] = tid - def get_id_info(self) -> dict: + def get_id_info(self) -> Dict[str,Any]: #minimal information for identifying the session return { "session-type" : "client", diff --git a/xpra/client/mixins/notifications.py b/xpra/client/mixins/notifications.py index 035b5d3581..53cb942ed2 100644 --- a/xpra/client/mixins/notifications.py +++ b/xpra/client/mixins/notifications.py @@ -1,9 +1,11 @@ # This file is part of Xpra. -# Copyright (C) 2010-2021 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. #pylint: disable-msg=E1101 +from typing import Dict, Any + from xpra.platform.paths import get_icon_filename from xpra.platform.gui import get_native_notifier_classes from xpra.util import envbool, repr_ellipsized, make_instance, updict, typedict, net_utf8 @@ -65,7 +67,7 @@ def parse_server_capabilities(self, c : typedict) -> bool: return True - def get_caps(self) -> dict: + def get_caps(self) -> Dict[str,Any]: enabled = self.client_supports_notifications actions = bool(self.client_supports_notifications and self.notifier and self.notifier.handles_actions) caps = updict({}, "notifications", { diff --git a/xpra/client/mixins/webcam.py b/xpra/client/mixins/webcam.py index aef390ccc9..74d0144494 100644 --- a/xpra/client/mixins/webcam.py +++ b/xpra/client/mixins/webcam.py @@ -6,6 +6,7 @@ from time import monotonic from threading import RLock +from typing import Dict, Any from xpra.log import Logger from xpra.scripts.config import FALSE_OPTIONS @@ -78,7 +79,7 @@ def init(self, opts): log("webcam forwarding: %s", self.webcam_forwarding) - def get_caps(self) -> dict: + def get_caps(self) -> Dict[str,Any]: if not self.webcam_forwarding: return {} return {"webcam" : True} diff --git a/xpra/clipboard/clipboard_core.py b/xpra/clipboard/clipboard_core.py index 12a9ed9519..5ff74ea16a 100644 --- a/xpra/clipboard/clipboard_core.py +++ b/xpra/clipboard/clipboard_core.py @@ -255,6 +255,9 @@ def claim(self) -> None: def get_contents(self, target:str, got_contents:Callable) -> None: pass + def got_token(self, targets, target_data=None, claim=True, _synchronous_client=False) -> None: + raise NotImplementedError() + def filter_data(self, dtype:str="" , dformat:int=0, data=None, trusted:bool=False, output_dtype=None): log("filter_data(%s, %s, %i %s, %s, %s)", @@ -480,7 +483,7 @@ def _process_clipboard_token(self, packet:Tuple) -> None: if proxy is None: #this can happen if the server has fewer clipboards than the client, #ie: with win32 shadow servers - l = log + l : Callable = log.debug if name in ALL_CLIPBOARDS: l = log.warn l("ignoring token for clipboard '%s' (no proxy)", name) diff --git a/xpra/codecs/argb/encoder.py b/xpra/codecs/argb/encoder.py index c62e4153c2..d43c76c48e 100644 --- a/xpra/codecs/argb/encoder.py +++ b/xpra/codecs/argb/encoder.py @@ -1,8 +1,10 @@ # This file is part of Xpra. -# Copyright (C) 2021 Antoine Martin +# Copyright (C) 2021-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. +from typing import Dict, Any + from xpra.codecs.rgb_transform import rgb_reformat from xpra.codecs import rgb_transform from xpra.net.compression import Compressed, LevelCompressed, compressed_wrapper @@ -20,7 +22,7 @@ def get_type() -> str: def get_encodings(): return "rgb24", "rgb32" -def get_info() -> dict: +def get_info() -> Dict[str,Any]: return { "version" : get_version(), "encodings" : get_encodings(), diff --git a/xpra/codecs/ffmpeg/colorspace_converter.pyx b/xpra/codecs/ffmpeg/colorspace_converter.pyx index 69c85c060c..483e83bd12 100644 --- a/xpra/codecs/ffmpeg/colorspace_converter.pyx +++ b/xpra/codecs/ffmpeg/colorspace_converter.pyx @@ -1,10 +1,12 @@ # This file is part of Xpra. # Copyright (C) 2013 Arthur Huillet -# Copyright (C) 2012-2022 Antoine Martin +# Copyright (C) 2012-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. from time import monotonic +from typing import Dict, Any + from xpra.log import Logger log = Logger("csc", "swscale") @@ -424,7 +426,7 @@ cdef class ColorspaceConverter: brightness, contrast, saturation)==-1: log.warn("Warning: cannot enable fullrange") - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = get_info() info.update({ "flags" : get_swscale_flags_strs(self.flags), diff --git a/xpra/codecs/ffmpeg/decoder.pyx b/xpra/codecs/ffmpeg/decoder.pyx index 6f5b6c0575..e974873cb4 100644 --- a/xpra/codecs/ffmpeg/decoder.pyx +++ b/xpra/codecs/ffmpeg/decoder.pyx @@ -1,5 +1,5 @@ # This file is part of Xpra. -# Copyright (C) 2012-2022 Antoine Martin +# Copyright (C) 2012-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -8,6 +8,7 @@ import errno import weakref from time import monotonic +from typing import Any, Dict from xpra.log import Logger log = Logger("decoder", "avcodec") @@ -830,7 +831,7 @@ cdef class Decoder: return "dec_avcodec.Decoder(*closed*)" return "dec_avcodec.Decoder(%s)" % self.get_info() - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = { "version" : get_version(), "encoding" : self.encoding, diff --git a/xpra/codecs/ffmpeg/encoder.pyx b/xpra/codecs/ffmpeg/encoder.pyx index 7f81658180..440ed6ddcf 100644 --- a/xpra/codecs/ffmpeg/encoder.pyx +++ b/xpra/codecs/ffmpeg/encoder.pyx @@ -1,5 +1,5 @@ # This file is part of Xpra. -# Copyright (C) 2017-2021 Antoine Martin +# Copyright (C) 2017-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -9,6 +9,8 @@ import os import time import errno import weakref +from typing import Any, Dict + from xpra.log import Logger log = Logger("encoder", "ffmpeg") @@ -1583,7 +1585,7 @@ cdef class Encoder: return "enc_ffmpeg.Encoder(*closed*)" return "enc_ffmpeg.Encoder(%s)" % self.get_info() - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = { "version" : get_version(), "encoding" : self.encoding, diff --git a/xpra/codecs/gstreamer/codec_common.py b/xpra/codecs/gstreamer/codec_common.py index 69bbac59da..90324e696f 100644 --- a/xpra/codecs/gstreamer/codec_common.py +++ b/xpra/codecs/gstreamer/codec_common.py @@ -202,14 +202,14 @@ class VideoPipeline(Pipeline): """ Dispatch video encoding or decoding to a gstreamer pipeline """ - def init_context(self, encoding:str, width:int, height:int, colorspace:int, options=None): + def init_context(self, encoding:str, width:int, height:int, colorspace:str, options=None): options = typedict(options or {}) self.encoding : str = encoding self.width : int = width self.height : int = height self.colorspace : str = colorspace self.frames : int = 0 - self.frame_queue = Queue() + self.frame_queue : Queue[Any] = Queue() self.pipeline_str : str = "" self.create_pipeline(options) self.src = self.pipeline.get_by_name("src") @@ -257,7 +257,7 @@ def process_buffer(self, buf): def get_info(self) -> Dict[str,Any]: info : Dict[str,Any] = get_info() - if self.colorspace is None: + if not self.colorspace: return info info.update({ "frames" : self.frames, @@ -270,15 +270,15 @@ def get_info(self) -> Dict[str,Any]: return info def __repr__(self): - if self.colorspace is None: + if not self.colorspace: return "gstreamer(uninitialized)" return f"gstreamer({self.colorspace} - {self.width}x{self.height})" def is_ready(self) -> bool: - return self.colorspace is not None + return bool(self.colorspace) def is_closed(self) -> bool: - return self.colorspace is None + return not bool(self.colorspace) def get_encoding(self) -> str: @@ -297,9 +297,8 @@ def clean(self) -> None: super().cleanup() self.width = 0 self.height = 0 - self.colorspace = None + self.colorspace = "" self.encoding = "" - self.dst_formats = [] self.frames = 0 diff --git a/xpra/codecs/gstreamer/encoder.py b/xpra/codecs/gstreamer/encoder.py index 4e06725208..e7bc0a0d65 100755 --- a/xpra/codecs/gstreamer/encoder.py +++ b/xpra/codecs/gstreamer/encoder.py @@ -221,7 +221,7 @@ def get_profile(self, options : dict): def get_src_format(self): return self.colorspace - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = super().get_info() if self.dst_formats: info["dst_formats"] = self.dst_formats diff --git a/xpra/codecs/jpeg/encoder.pyx b/xpra/codecs/jpeg/encoder.pyx index b81cc6e9e4..72a730421a 100644 --- a/xpra/codecs/jpeg/encoder.pyx +++ b/xpra/codecs/jpeg/encoder.pyx @@ -1,10 +1,11 @@ # This file is part of Xpra. -# Copyright (C) 2017-2022 Antoine Martin +# Copyright (C) 2017-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. #cython: wraparound=False +from typing import Dict, Any from time import monotonic from libc.stdint cimport uintptr_t @@ -218,7 +219,7 @@ cdef class Encoder: def get_src_format(self): return self.src_format - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = get_info() info.update({ "frames" : int(self.frames), diff --git a/xpra/codecs/libyuv/colorspace_converter.pyx b/xpra/codecs/libyuv/colorspace_converter.pyx index 3288554621..c07c3598d1 100644 --- a/xpra/codecs/libyuv/colorspace_converter.pyx +++ b/xpra/codecs/libyuv/colorspace_converter.pyx @@ -6,6 +6,7 @@ #cython: wraparound=False +from typing import Dict, Any from time import monotonic from xpra.log import Logger @@ -139,7 +140,7 @@ COLORSPACES = { "BGRX" : ("YUV420P", "NV12"), "NV12" : ("RGB", "BGRX", "RGBX"), } -def get_info(): +def get_info() -> Dict[str,Any]: return { "version" : get_version(), "formats" : COLORSPACES, @@ -349,7 +350,7 @@ cdef class ColorspaceConverter: log("buffer size=%i, yuv_scaling=%s, rgb_scaling=%s, filtermode=%s", self.out_buffer_size, self.yuv_scaling, self.rgb_scaling, get_fiter_mode_str(self.filtermode)) - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = get_info() info.update({ "frames" : int(self.frames), diff --git a/xpra/codecs/nvidia/nvdec/decoder.pyx b/xpra/codecs/nvidia/nvdec/decoder.pyx index 3b581148da..655b6d0b5a 100644 --- a/xpra/codecs/nvidia/nvdec/decoder.pyx +++ b/xpra/codecs/nvidia/nvdec/decoder.pyx @@ -6,12 +6,13 @@ from libc.string cimport memset from libc.stdint cimport uintptr_t from libc.stdio cimport printf -from xpra.util import AtomicInteger from xpra.buffers.membuf cimport getbuf, buffer_context, MemBuf #pylint: disable=syntax-error + from weakref import WeakValueDictionary +from typing import Dict, Any from threading import Event -from xpra.util import csv +from xpra.util import csv, AtomicInteger from xpra.codecs.image_wrapper import ImageWrapper from xpra.codecs.nvidia.cuda_errors import cudacheck, get_error_name from xpra.codecs.nvidia.cuda_context import get_default_device_context @@ -591,7 +592,7 @@ cdef class Decoder: def __repr__(self): return f"nvdec({self.encoding})" - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return { "type" : self.get_type(), "width" : self.width, diff --git a/xpra/codecs/nvidia/nvenc/encoder.pyx b/xpra/codecs/nvidia/nvenc/encoder.pyx index 3962521e6f..9d3d5a52a6 100644 --- a/xpra/codecs/nvidia/nvenc/encoder.pyx +++ b/xpra/codecs/nvidia/nvenc/encoder.pyx @@ -1,5 +1,5 @@ # This file is part of Xpra. -# Copyright (C) 2013-2022 Antoine Martin +# Copyright (C) 2013-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -8,6 +8,7 @@ import os import platform from collections import deque from time import monotonic +from typing import Dict, Any import ctypes from ctypes import cdll, POINTER from threading import Lock @@ -1442,7 +1443,7 @@ def get_version(): def get_type() -> str: return "nvenc" -def get_info() -> dict: +def get_info() -> Dict[str,Any]: global last_context_failure, context_counter, context_gen_counter info = { "version" : PRETTY_VERSION, @@ -2093,7 +2094,7 @@ cdef class Encoder: raise RuntimeError("bitstream buffer pointer is null") - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: global YUV444_CODEC_SUPPORT, YUV444_ENABLED, LOSSLESS_CODEC_SUPPORT, LOSSLESS_ENABLED cdef double pps info = get_info() diff --git a/xpra/codecs/nvidia/nvfbc/fbc_capture_linux.pyx b/xpra/codecs/nvidia/nvfbc/fbc_capture_linux.pyx index 3b10cd4d32..e74091b2ca 100644 --- a/xpra/codecs/nvidia/nvfbc/fbc_capture_linux.pyx +++ b/xpra/codecs/nvidia/nvfbc/fbc_capture_linux.pyx @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2017-2021 Antoine Martin +# Copyright (C) 2017-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -9,6 +9,7 @@ import os from weakref import WeakSet from time import monotonic +from typing import Dict, Any from xpra.util import csv, roundup, envbool from xpra.codecs.image_wrapper import ImageWrapper @@ -459,7 +460,7 @@ def get_version(): def get_type(): return "nvfbc" -def get_info(): +def get_info() -> Dict[str,Any]: info = { "type" : "nvfbc", "version" : get_version(), @@ -523,7 +524,7 @@ cdef class NvFBC_SysCapture: def raiseNvFBC(self, NVFBCSTATUS ret, msg): raiseNvFBC(self.context, ret, msg) - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = get_info() info["pixel-format"] = self.pixel_format return info @@ -655,7 +656,7 @@ cdef class NvFBC_CUDACapture: def raiseNvFBC(self, NVFBCSTATUS ret, msg): raiseNvFBC(self.context, ret, msg) - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = get_info() info["pixel-format"] = self.pixel_format return info diff --git a/xpra/codecs/nvidia/nvfbc/fbc_capture_win.pyx b/xpra/codecs/nvidia/nvfbc/fbc_capture_win.pyx index 61b005afd2..8a1c625350 100644 --- a/xpra/codecs/nvidia/nvfbc/fbc_capture_win.pyx +++ b/xpra/codecs/nvidia/nvfbc/fbc_capture_win.pyx @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2017-2022 Antoine Martin +# Copyright (C) 2017-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -9,6 +9,7 @@ import os import sys from time import monotonic +from typing import Dict, Any from xpra.os_util import WIN32 from xpra.util import csv, roundup @@ -540,7 +541,7 @@ def get_version(): def get_type(): return "nvfbc" -def get_info(): +def get_info() -> Dict[str,Any]: info = { "type" : "nvfbc", "version" : get_version(), @@ -601,7 +602,7 @@ cdef class NvFBC_SysCapture: raiseNvFBC(res, "NvFBCToSysSetUp") self.setup = True - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = get_info() info["pixel-format"] = self.pixel_format return info @@ -744,7 +745,7 @@ cdef class NvFBC_CUDACapture: raiseNvFBC(res, "NvFBCCudaSetup") self.setup = True - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = get_info() info["pixel-format"] = self.pixel_format return info diff --git a/xpra/codecs/nvidia/nvjpeg/encoder.pyx b/xpra/codecs/nvidia/nvjpeg/encoder.pyx index 9ef0291837..b8117584b0 100644 --- a/xpra/codecs/nvidia/nvjpeg/encoder.pyx +++ b/xpra/codecs/nvidia/nvjpeg/encoder.pyx @@ -1,10 +1,11 @@ # This file is part of Xpra. -# Copyright (C) 2021-2022 Antoine Martin +# Copyright (C) 2021-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. from time import monotonic from math import ceil +from typing import Dict, Any from libc.stdint cimport uintptr_t from xpra.buffers.membuf cimport getbuf, MemBuf #pylint: disable=syntax-error @@ -291,7 +292,7 @@ cdef class Encoder: def get_src_format(self): return self.src_format - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = get_info() info.update({ "frames" : int(self.frames), diff --git a/xpra/codecs/openh264/decoder.pyx b/xpra/codecs/openh264/decoder.pyx index 1233996aa2..7170d6d6e9 100644 --- a/xpra/codecs/openh264/decoder.pyx +++ b/xpra/codecs/openh264/decoder.pyx @@ -1,12 +1,12 @@ # This file is part of Xpra. -# Copyright (C) 2022 Antoine Martin +# Copyright (C) 2022-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. #cython: wraparound=False -import os from time import monotonic +from typing import Dict, Any from xpra.codecs.image_wrapper import ImageWrapper from xpra.log import Logger @@ -157,7 +157,7 @@ cdef class Decoder: self.height = 0 self.colorspace = "" - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = get_info() info.update({ "frames" : int(self.frames), diff --git a/xpra/codecs/openh264/encoder.pyx b/xpra/codecs/openh264/encoder.pyx index e153660e08..d402e08ddf 100644 --- a/xpra/codecs/openh264/encoder.pyx +++ b/xpra/codecs/openh264/encoder.pyx @@ -7,6 +7,7 @@ import os from time import monotonic +from typing import Dict, Any from xpra.log import Logger log = Logger("encoder", "openh264") @@ -371,7 +372,7 @@ cdef class Encoder: f.close() - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = get_info() info.update({ "frames" : int(self.frames), diff --git a/xpra/codecs/pillow/decoder.py b/xpra/codecs/pillow/decoder.py index 6ad441c14c..2b6b84afad 100644 --- a/xpra/codecs/pillow/decoder.py +++ b/xpra/codecs/pillow/decoder.py @@ -8,7 +8,7 @@ from io import BytesIO import PIL #@UnresolvedImport from PIL import Image #@UnresolvedImport -from typing import Callable, Tuple +from typing import Callable, Tuple, Dict, Any from xpra.util import csv, typedict from xpra.os_util import hexstr, strtobytes @@ -98,7 +98,7 @@ def get_encodings() -> Tuple[str]: ENCODINGS = tuple(do_get_encodings()) -def get_info() -> dict: +def get_info() -> Dict[str,Any]: return { "version" : get_version(), "encodings" : get_encodings(), diff --git a/xpra/codecs/pillow/encoder.py b/xpra/codecs/pillow/encoder.py index 79e512be97..c77b2eced2 100644 --- a/xpra/codecs/pillow/encoder.py +++ b/xpra/codecs/pillow/encoder.py @@ -7,7 +7,7 @@ from io import BytesIO import PIL from PIL import Image, ImagePalette #@UnresolvedImport -from typing import Tuple, List, Any +from typing import Dict, Tuple, List, Any from xpra.codecs.codec_debug import may_save_image from xpra.util import csv @@ -57,7 +57,7 @@ def get_encodings() -> Tuple[str, ...]: ENCODINGS : Tuple[str, ...] = do_get_encodings() -def get_info() -> dict[str,Any]: +def get_info() -> Dict[str,Any]: return { "version" : get_version(), "encodings" : get_encodings(), diff --git a/xpra/codecs/proxy/encoder.py b/xpra/codecs/proxy/encoder.py index 492ec924d9..5fd198a367 100755 --- a/xpra/codecs/proxy/encoder.py +++ b/xpra/codecs/proxy/encoder.py @@ -1,10 +1,11 @@ # This file is part of Xpra. -# Copyright (C) 2014-2021 Antoine Martin +# Copyright (C) 2014-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. from time import monotonic from collections import deque +from typing import Dict, Any, Tuple from xpra.codecs.image_wrapper import ImageWrapper from xpra.util import typedict @@ -14,22 +15,22 @@ log = Logger("encoder", "proxy") -def get_version(): +def get_version() -> Tuple[int, ...]: return (0, 2) -def get_type(): +def get_type() -> str: return "proxy" -def get_info(): +def get_info() -> Dict[str,Any]: return {"version" : get_version()} -def get_encodings(): +def get_encodings() -> Tuple[str, ...]: return ("proxy", ) -def init_module(): +def init_module() -> None: log("enc_proxy.init_module()") -def cleanup_module(): +def cleanup_module() -> None: log("enc_proxy.cleanup_module()") @@ -39,7 +40,7 @@ class Encoder: the raw pixels and the metadata that goes with it. """ - def init_context(self, encoding, width, height, src_format, options=None): + def init_context(self, encoding:str, width:int, height:int, src_format:str, options=None) -> None: options = typedict(options or {}) self.encoding = encoding self.width = width @@ -51,10 +52,10 @@ def init_context(self, encoding, width, height, src_format, options=None): self.time = 0 self.first_frame_timestamp = 0 - def is_ready(self): + def is_ready(self) -> bool: return True - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = get_info() if self.src_format is None: return info @@ -84,25 +85,25 @@ def __repr__(self): return "proxy_encoder(uninitialized)" return f"proxy_encoder({self.src_format} - {self.width}x{self.height})" - def is_closed(self): + def is_closed(self) -> bool: return self.src_format is None - def get_encoding(self): + def get_encoding(self) -> str: return self.encoding - def get_width(self): + def get_width(self) -> int: return self.width - def get_height(self): + def get_height(self) -> int: return self.height - def get_type(self): + def get_type(self) -> str: return "proxy" - def get_src_format(self): + def get_src_format(self) -> str: return self.src_format - def clean(self): + def clean(self) -> None: self.width = 0 self.height = 0 self.src_format = None @@ -114,7 +115,7 @@ def clean(self): self.time = 0 self.first_frame_timestamp = 0 - def compress_image(self, image, options=None): + def compress_image(self, image:ImageWrapper, options=None) -> Tuple[bytes,dict]: log("compress_image(%s, %s)", image, options) #pass the pixels as they are if image.get_planes()!=ImageWrapper.PACKED: @@ -142,4 +143,4 @@ def compress_image(self, image, options=None): log("compress_image(%s, %s) returning %s bytes and options=%s", image, options, len(pixels), client_options) self.last_frame_times.append(monotonic()) self.frames += 1 - return memoryview_to_bytes(pixels[:]), client_options + return memoryview_to_bytes(pixels[:]), client_options diff --git a/xpra/codecs/v4l2/pusher.pyx b/xpra/codecs/v4l2/pusher.pyx index 5cfcfd05db..a3ed9678c9 100644 --- a/xpra/codecs/v4l2/pusher.pyx +++ b/xpra/codecs/v4l2/pusher.pyx @@ -1,13 +1,13 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2016-2021 Antoine Martin +# Copyright (C) 2016-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. #cython: wraparound=False -import time import os +from typing import Dict, Any from xpra.log import Logger log = Logger("webcam") @@ -383,7 +383,7 @@ cdef class Pusher: self.device = None d.close() - def get_info(self) -> dict: #@DuplicatedSignature + def get_info(self) -> Dict[str,Any]: #@DuplicatedSignature info = get_info() info.update({ "frames" : int(self.frames), diff --git a/xpra/codecs/vpx/decoder.pyx b/xpra/codecs/vpx/decoder.pyx index 31e1fd54e0..39ffac3632 100644 --- a/xpra/codecs/vpx/decoder.pyx +++ b/xpra/codecs/vpx/decoder.pyx @@ -1,5 +1,5 @@ # This file is part of Xpra. -# Copyright (C) 2012-2022 Antoine Martin +# Copyright (C) 2012-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -7,6 +7,7 @@ import os from time import monotonic +from typing import Dict, Tuple, Any from xpra.log import Logger log = Logger("decoder", "vpx") @@ -36,7 +37,7 @@ from xpra.buffers.membuf cimport padbuf, MemBuf, buffer_context #pylint: disable SAVE_TO_FILE = envbool("XPRA_SAVE_TO_FILE") -VPX_COLOR_SPACES = { +VPX_COLOR_SPACES : Dict[int,str] = { VPX_CS_UNKNOWN : "unknown", VPX_CS_BT_601 : "BT601", VPX_CS_BT_709 : "BT709", @@ -47,13 +48,13 @@ VPX_COLOR_SPACES = { VPX_CS_SRGB : "SRGB", } -VPX_COLOR_RANGES = { +VPX_COLOR_RANGES : Dict[int,str] = { VPX_CR_STUDIO_RANGE : "studio", VPX_CR_FULL_RANGE : " full", } -cpus = os.cpu_count() +cdef unsigned int cpus = os.cpu_count() cdef int VPX_THREADS = envint("XPRA_VPX_THREADS", max(1, cpus-1)) cdef inline int roundup(int n, int m): @@ -91,47 +92,50 @@ cdef extern from "vpx/vpx_decoder.h": #https://groups.google.com/a/webmproject.org/forum/?fromgroups#!msg/webm-discuss/f5Rmi-Cu63k/IXIzwVoXt_wJ #"RGB is not supported. You need to convert your source to YUV, and then compress that." -CODECS = ("vp8", "vp9") -COLORSPACES = { +CODECS : Tuple[str, ...] = ("vp8", "vp9") +COLORSPACES : Dict[str,Tuple[str,...]] = { "vp8" : ("YUV420P", ), "vp9" : ("YUV420P", "YUV444P"), } -def init_module(): +def init_module() -> None: log("vpx.decoder.init_module() info=%s", get_info()) log("supported codecs: %s", CODECS) log("supported colorspaces: %s", COLORSPACES) -def cleanup_module(): +def cleanup_module() -> None: log("vpx.decoder.cleanup_module()") -def get_abi_version(): +def get_abi_version() -> int: return VPX_DECODER_ABI_VERSION -def get_version(): +def get_version() -> Tuple[int]: b = vpx_codec_version_str() vstr = b.decode("latin1").lstrip("v") log("vpx_codec_version_str()=%s", vstr) + vparts : List[int] = [] try: - return tuple(int(v) for v in vstr.split(".")) + for x in vstr.split("."): + vparts.append(int(x)) except Exception: - return vstr + pass + return tuple(vparts) -def get_type(): +def get_type() -> str: return "vpx" -def get_encodings(): +def get_encodings() -> Tuple[str, ...]: return CODECS -def get_min_size(encoding): +def get_min_size(encoding:str) -> Tuple[int, int]: return 16, 16 -def get_input_colorspaces(encoding): +def get_input_colorspaces(encoding:str) -> Tuple[str,...]: assert encoding in CODECS return COLORSPACES.get(encoding) -def get_output_colorspace(encoding, csc): +def get_output_colorspace(encoding:str, csc:str) -> str: #same as input assert encoding in CODECS colorspaces = COLORSPACES.get(encoding) @@ -139,7 +143,7 @@ def get_output_colorspace(encoding, csc): return csc -def get_info(): +def get_info() -> Dict[str,Any]: global CODECS info = { "version" : get_version(), @@ -212,7 +216,7 @@ cdef class Decoder: def __repr__(self): return "vpx.Decoder(%s)" % self.encoding - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return { "type" : self.get_type(), "width" : self.get_width(), @@ -223,22 +227,22 @@ cdef class Decoder: "max_threads" : self.max_threads, } - def get_colorspace(self): + def get_colorspace(self) -> str: return self.dst_format - def get_width(self): + def get_width(self) -> int: return self.width - def get_height(self): + def get_height(self) -> int: return self.height - def is_closed(self): + def is_closed(self) -> bool: return self.context==NULL - def get_encoding(self): + def get_encoding(self) -> str: return self.encoding - def get_type(self): + def get_type(self) -> str: return "vpx" def __dealloc__(self): @@ -260,7 +264,7 @@ cdef class Decoder: f.close() - def decompress_image(self, data, options=None): + def decompress_image(self, data:bytes, options=None) -> ImageWrapper: cdef vpx_codec_iter_t citer = NULL cdef MemBuf output_buf cdef void *output @@ -317,7 +321,7 @@ cdef class Decoder: self.encoding, self.frames, elapsed, VPX_COLOR_SPACES.get(img.cs, img.cs), VPX_COLOR_RANGES.get(img.range, img.range)) return ImageWrapper(0, 0, self.width, self.height, pixels, self.get_colorspace(), 24, strides, 1, ImageWrapper.PLANAR_3) - def codec_error_str(self): + def codec_error_str(self) -> str: return vpx_codec_error(self.context).decode("latin1") diff --git a/xpra/codecs/vpx/encoder.pyx b/xpra/codecs/vpx/encoder.pyx index 2060b1cf60..a124ac97b6 100644 --- a/xpra/codecs/vpx/encoder.pyx +++ b/xpra/codecs/vpx/encoder.pyx @@ -1,5 +1,5 @@ # This file is part of Xpra. -# Copyright (C) 2012-2022 Antoine Martin +# Copyright (C) 2012-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -7,6 +7,7 @@ import os import math from collections import deque from time import monotonic +from typing import Dict, Any from xpra.log import Logger log = Logger("encoder", "vpx") @@ -230,7 +231,7 @@ def get_output_colorspaces(encoding, input_colorspace): generation = AtomicInteger() -def get_info(): +def get_info() -> Dict[str,Any]: global CODECS, MAX_SIZE b = vpx_codec_build_config() info = { @@ -468,7 +469,7 @@ cdef class Encoder: def __repr__(self): return "vpx.Encoder(%s)" % self.encoding - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = get_info() info.update({ "frames" : int(self.frames), diff --git a/xpra/codecs/webp/encoder.pyx b/xpra/codecs/webp/encoder.pyx index 71193f4471..e9b9d00331 100644 --- a/xpra/codecs/webp/encoder.pyx +++ b/xpra/codecs/webp/encoder.pyx @@ -1,10 +1,11 @@ # This file is part of Xpra. -# Copyright (C) 2014-2022 Antoine Martin +# Copyright (C) 2014-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import os from time import monotonic +from typing import Dict, Any from libc.stdint cimport uint8_t, uint32_t, uintptr_t #pylint: disable=syntax-error from libc.stdlib cimport free #pylint: disable=syntax-error @@ -496,7 +497,7 @@ cdef class Encoder: def get_src_format(self): return self.src_format - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = get_info() info.update({ "frames" : int(self.frames), diff --git a/xpra/codecs/x264/encoder.pyx b/xpra/codecs/x264/encoder.pyx index b49b790227..0d96cff4c4 100644 --- a/xpra/codecs/x264/encoder.pyx +++ b/xpra/codecs/x264/encoder.pyx @@ -1,5 +1,5 @@ # This file is part of Xpra. -# Copyright (C) 2012-2021 Antoine Martin +# Copyright (C) 2012-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -7,6 +7,7 @@ import os from time import monotonic +from typing import Dict, Any, Tuple from xpra.log import Logger log = Logger("encoder", "x264") @@ -335,7 +336,7 @@ I422_PROFILES = [PROFILE_HIGH422, PROFILE_HIGH444] I444_PROFILES = [PROFILE_HIGH444] RGB_PROFILES = [PROFILE_HIGH444] -COLORSPACE_FORMATS = { +COLORSPACE_FORMATS : Dict[str,Tuple] = { "YUV420P" : (X264_CSP_I420, PROFILE_HIGH, I420_PROFILES), "YUV422P" : (X264_CSP_I422, PROFILE_HIGH422, I422_PROFILES), "YUV444P" : (X264_CSP_I444, PROFILE_HIGH444, I444_PROFILES), @@ -347,7 +348,7 @@ if SUPPORT_24BPP: "RGB" : (X264_CSP_RGB, PROFILE_HIGH444, RGB_PROFILES), }) -COLORSPACES = { +COLORSPACES : Dict[str,str] = { "YUV420P" : "YUV420P", "YUV422P" : "YUV422P", "YUV444P" : "YUV444P", @@ -363,20 +364,20 @@ if SUPPORT_24BPP: }) -def init_module(): +def init_module() -> None: log("enc_x264.init_module()") -def cleanup_module(): +def cleanup_module() -> None: log("enc_x264.cleanup_module()") -def get_version(): +def get_version() -> Tuple[int]: return (X264_BUILD, ) -def get_type(): +def get_type() -> str: return "x264" generation = AtomicInteger() -def get_info(): +def get_info() -> Dict[str,Any]: global COLORSPACES, MAX_WIDTH, MAX_HEIGHT return { "version" : get_version(), @@ -385,14 +386,14 @@ def get_info(): "formats" : tuple(COLORSPACES.keys()), } -def get_encodings(): +def get_encodings() -> Tuple[str,...]: return ("h264", ) -def get_input_colorspaces(encoding): +def get_input_colorspaces(encoding:str): assert encoding in get_encodings() return tuple(COLORSPACES.keys()) -def get_output_colorspaces(encoding, input_colorspace): +def get_output_colorspaces(encoding:str, input_colorspace:str): assert encoding in get_encodings() assert input_colorspace in COLORSPACES return (COLORSPACES[input_colorspace],) @@ -425,7 +426,7 @@ def get_specs(encoding, colorspace): #maps a log level to one of our logger functions: -LOGGERS = { +LOGGERS : Dict[int,Callable] = { X264_LOG_ERROR : log.error, X264_LOG_WARNING : log.warn, X264_LOG_INFO : log.info, @@ -433,7 +434,7 @@ LOGGERS = { } #maps a log level string to the actual constant: -LOG_LEVEL = { +LOG_LEVEL : Dict[str,int] = { "ERROR" : X264_LOG_ERROR, "WARNING" : X264_LOG_WARNING, "WARN" : X264_LOG_WARNING, @@ -545,13 +546,13 @@ cdef class Encoder: self.blank_buffer = b"\0" * (self.width * self.height * 4) self.ready = 1 - def is_ready(self): + def is_ready(self) -> bool: return bool(self.ready) - def get_tune(self): + def get_tune(self) -> bytes: log("x264: get_tune() TUNE=%s, fast_decode=%s, content_type=%s", TUNE, self.fast_decode, self.content_type) if TUNE: - return TUNE + return TUNE.encode() tunes = [] if self.content_type.find("video")>=0: tunes.append(b"film") @@ -642,7 +643,7 @@ cdef class Encoder: param.i_log_level = LOG_LEVEL - def clean(self): + def clean(self) -> None: log("x264 close context %#x", self.context) cdef x264_t *context = self.context if context!=NULL: @@ -670,7 +671,7 @@ cdef class Encoder: f.close() - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: cdef double pps if self.profile is None: return {} @@ -779,25 +780,25 @@ cdef class Encoder: return "x264_encoder(uninitialized)" return "x264_encoder(%s - %sx%s)" % (self.src_format, self.width, self.height) - def is_closed(self): + def is_closed(self) -> bool: return self.context==NULL - def get_encoding(self): + def get_encoding(self) -> str: return "h264" def __dealloc__(self): self.clean() - def get_width(self): + def get_width(self) -> int: return self.width - def get_height(self): + def get_height(self) -> int: return self.height - def get_type(self): + def get_type(self) -> str: return "x264" - def get_src_format(self): + def get_src_format(self) -> str: return self.src_format @@ -966,7 +967,7 @@ cdef class Encoder: return self.do_compress_image(NULL) - def set_encoding_speed(self, int pct): + def set_encoding_speed(self, int pct) -> None: assert pct>=0 and pct<=100, "invalid percentage: %s" % pct assert self.context!=NULL, "context is closed!" cdef x264_param_t param @@ -983,7 +984,7 @@ cdef class Encoder: self.do_reconfig_tune(¶m) self.preset = new_preset - def set_encoding_quality(self, int pct): + def set_encoding_quality(self, int pct) -> None: assert pct>=0 and pct<=100, "invalid percentage: %s" % pct if self.quality==pct: return @@ -995,7 +996,7 @@ cdef class Encoder: self.reconfig_tune() - def reconfig_tune(self): + def reconfig_tune(self) -> None: cdef x264_param_t param x264_encoder_parameters(self.context, ¶m) self.do_reconfig_tune(¶m) diff --git a/xpra/codecs/x265/encoder.pyx b/xpra/codecs/x265/encoder.pyx index fe351ffd25..981f3f8398 100644 --- a/xpra/codecs/x265/encoder.pyx +++ b/xpra/codecs/x265/encoder.pyx @@ -446,7 +446,7 @@ cdef class Encoder: self.first_frame_timestamp = 0 - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: cdef float pps if self.profile is None: return {} diff --git a/xpra/dbus/notifications_forwarder.py b/xpra/dbus/notifications_forwarder.py index 203c0923a6..fdff14032d 100755 --- a/xpra/dbus/notifications_forwarder.py +++ b/xpra/dbus/notifications_forwarder.py @@ -1,10 +1,11 @@ # This file is part of Xpra. -# Copyright (C) 2011-2018 Antoine Martin +# Copyright (C) 2011-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import os import dbus.service +from typing import Dict, Any from xpra.notifications.common import parse_image_data, parse_image_path from xpra.dbus.helper import dbus_to_native @@ -40,7 +41,7 @@ def __init__(self, bus, notify_callback=None, close_callback=None): bus_name = dbus.service.BusName(BUS_NAME, bus=bus) super().__init__(bus_name, BUS_PATH) - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return { "active" : tuple(self.active_notifications), "counter" : self.counter, diff --git a/xpra/gtk_common/gtk_clipboard.py b/xpra/gtk_common/gtk_clipboard.py index 11ad85f078..5f2fdb7fce 100644 --- a/xpra/gtk_common/gtk_clipboard.py +++ b/xpra/gtk_common/gtk_clipboard.py @@ -59,7 +59,7 @@ def __init__(self, selection="CLIPBOARD"): def __repr__(self): return "GTKClipboardProxy(%s)" % self._selection - def got_token(self, targets, target_data=None, claim=True, synchronous_client=False): + def got_token(self, targets, target_data=None, claim=True, synchronous_client=False) -> None: # the remote end now owns the clipboard self.cancel_emit_token() if not self._enabled: diff --git a/xpra/gtk_common/gtk_util.py b/xpra/gtk_common/gtk_util.py index d4565a215d..69840160fd 100644 --- a/xpra/gtk_common/gtk_util.py +++ b/xpra/gtk_common/gtk_util.py @@ -29,7 +29,7 @@ GTK_WORKAREA = envbool("XPRA_GTK_WORKAREA", True) GTK_VERSION_INFO : Dict[str,Tuple[Any, ...]]= {} -def get_gtk_version_info() -> dict: +def get_gtk_version_info() -> Dict[str,Any]: #update props given: global GTK_VERSION_INFO def av(k, v): diff --git a/xpra/keyboard/layouts.py b/xpra/keyboard/layouts.py index 673062934c..856bb984a2 100644 --- a/xpra/keyboard/layouts.py +++ b/xpra/keyboard/layouts.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2011-2020 Antoine Martin +# Copyright (C) 2011-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. +from typing import Dict, Any, Tuple, List + # The data for this table can be found mostly here: # http://msdn.microsoft.com/en-us/library/aa912040.aspx # and here: @@ -19,7 +21,7 @@ ES_VARIANTS : list[str] = ["nodeadkeys", "deadtilde", "sundeadkeys", "dvorak", "est", "cat", "mac"] RS_VARIANTS : list[str] = ["yz", "latin", "latinunicode", "latinyz", "latinunicodeyz", "alternatequotes", "latinalternatequotes", "rue"] FR_VARIANTS : list[str] = ["nodeadkeys", "sundeadkeys", "oss", "oss_latin9", "oss_nodeadkeys", "oss_sundeadkeys", "latin9", "latin9_nodeadkeys", "latin9_sundeadkeys", "bepo", "bepo_latin9", "dvorak", "mac", "bre", "oci", "geo"] -WIN32_LAYOUTS : dict[int,tuple]= { +WIN32_LAYOUTS : Dict[int,Tuple[str, str, str, int, str, List[str]]]= { 1025: ("ARA", "Saudi Arabia", "Arabic", 1356, "ar", []), 1026: ("BGR", "Bulgaria", "Bulgarian", 1251, "bg", ["phonetic", "bas_phonetic"]), 1027: ("CAT", "Spain", "Catalan", 1252, "ad", []), @@ -167,7 +169,7 @@ #map win32 keyboard codes to x11 names: #based on #https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/windows-language-pack-default-values -WIN32_KEYBOARDS : dict[int, tuple] = { +WIN32_KEYBOARDS : Dict[int, Tuple[str, str]] = { 0x0000041c : ("al", "Albania"), 0x00000401 : ("ar", "Arabic (101)"), 0x00010401 : ("ar", "Arabic (102)"), @@ -375,7 +377,7 @@ # This is generated from the table above so we can # let the user choose his own layout. # (country,language) : (layout,variant) -X11_LAYOUTS : dict[tuple,tuple] = {} +X11_LAYOUTS : Dict[Tuple,Tuple] = {} for _, country, language, _, layout, variants in WIN32_LAYOUTS.values(): key = (country,language) value = (layout, variants) @@ -390,7 +392,7 @@ if variant not in l: l.append(variant) -def parse_xkbmap_query(xkbmap_query:str) -> dict: +def parse_xkbmap_query(xkbmap_query:str) -> Dict[str,Any]: """ parses the output of "setxkbmap -query" into a dict """ import re settings = {} diff --git a/xpra/log.py b/xpra/log.py index 9f2af949d2..268ab98b1a 100644 --- a/xpra/log.py +++ b/xpra/log.py @@ -9,7 +9,7 @@ import logging import weakref import itertools -from typing import Callable +from typing import Callable, Dict, Any # This module is used by non-GUI programs and thus must not import gtk. LOG_PREFIX : str = "" @@ -355,7 +355,7 @@ def isenvdebug(category : str) -> bool: return os.environ.get("XPRA_%s_DEBUG" % category.upper().replace("-", "_").replace("+", "_"), "0")=="1" -def get_info() -> dict: +def get_info() -> Dict[str,Any]: info = { "categories" : { "enabled" : tuple(debug_enabled_categories), @@ -431,7 +431,7 @@ def __init__(self, *categories): if self.debug_enabled: self.debug("debug enabled for %s / %s", caller, categories) - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return { "categories" : self.categories, "debug" : self.debug_enabled, diff --git a/xpra/net/compression.py b/xpra/net/compression.py index 292ca87b7b..9f9c634f06 100644 --- a/xpra/net/compression.py +++ b/xpra/net/compression.py @@ -105,8 +105,8 @@ def use(compressor) -> bool: return compressor in COMPRESSION -def get_compression_caps(full_info : int=1) -> dict[str,Any]: - caps : dict[str,Any] = {} +def get_compression_caps(full_info : int=1) -> Dict[str,Any]: + caps : Dict[str,Any] = {} for x in ALL_COMPRESSORS: c = COMPRESSION.get(x) if c is None: diff --git a/xpra/net/crypto.py b/xpra/net/crypto.py index 2b12a42669..e32f532e2a 100644 --- a/xpra/net/crypto.py +++ b/xpra/net/crypto.py @@ -1,5 +1,5 @@ # This file is part of Xpra. -# Copyright (C) 2011-2022 Antoine Martin +# Copyright (C) 2011-2023 Antoine Martin # Copyright (C) 2008, 2009, 2010 Nathaniel Smith # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -8,6 +8,7 @@ import sys import secrets from struct import pack +from typing import Dict, Any from xpra.util import envint, envbool, csv from xpra.version_util import parse_version @@ -189,7 +190,7 @@ def get_iterations() -> int: return DEFAULT_ITERATIONS -def new_cipher_caps(proto, cipher, cipher_mode, encryption_key, padding_options) -> dict: +def new_cipher_caps(proto, cipher:str, cipher_mode:str, encryption_key, padding_options) -> Dict[str,Any]: iv = get_iv() key_salt = get_salt() key_size = DEFAULT_KEYSIZE @@ -221,7 +222,7 @@ def new_cipher_caps(proto, cipher, cipher_mode, encryption_key, padding_options) caps["cipher"] = cipher return caps -def get_crypto_caps(full=True) -> dict: +def get_crypto_caps(full=True) -> Dict[str,Any]: crypto_backend_init() caps = { "padding" : {"options" : PADDING_OPTIONS}, diff --git a/xpra/net/file_transfer.py b/xpra/net/file_transfer.py index 3a5e7bc677..4d07d3b9b1 100644 --- a/xpra/net/file_transfer.py +++ b/xpra/net/file_transfer.py @@ -10,6 +10,7 @@ import uuid from time import monotonic from dataclasses import dataclass +from typing import Dict, Any, Optional, Callable from xpra.child_reaper import getChildReaper from xpra.os_util import bytestostr, strtobytes, umask_context, POSIX, WIN32 @@ -158,7 +159,7 @@ def pask(v): self.file_request_callback = {} filelog("file transfer attributes=%s", self.get_file_transfer_features()) - def get_file_transfer_features(self) -> dict: + def get_file_transfer_features(self) -> Dict[str,Any]: #used in hello packets, #duplicated with namespace (old caps to be removed in v6) return { @@ -178,10 +179,10 @@ def get_file_transfer_features(self) -> dict: "file" : self.get_file_transfer_info(), } - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return self.get_file_transfer_info() - def get_file_transfer_info(self) -> dict: + def get_file_transfer_info(self) -> Dict[str,Any]: #slightly different from above... for legacy reasons #this one is used for get_info() in a proper "file." namespace from server_base.py return { @@ -287,7 +288,7 @@ def dump_remote_caps(self): filelog("file transfer remote caps: open-url=%-5s (ask=%s)", self.remote_open_url, self.remote_open_url_ask) - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = super().get_info() info["remote"] = { "file-transfer" : self.remote_file_transfer, @@ -305,7 +306,7 @@ def get_info(self) -> dict: return info - def digest_mismatch(self, filename, digest, expected_digest): + def digest_mismatch(self, filename:str, digest, expected_digest): filelog.error(f"Error: data does not match, invalid {digest.name} file digest") filelog.error(f" for {filename!r}") filelog.error(f" received {digest.hexdigest()}") @@ -317,7 +318,7 @@ def digest_mismatch(self, filename, digest, expected_digest): filelog.error(f"Error: failed to delete uploaded file {filename}") - def _check_chunk_receiving(self, chunk_id, chunk_no): + def _check_chunk_receiving(self, chunk_id:int, chunk_no:int): chunk_state = self.receive_chunks_in_progress.get(chunk_id) filelog("_check_chunk_receiving(%s, %s) chunk_state=%s", chunk_id, chunk_no, chunk_state) if not chunk_state: @@ -331,7 +332,7 @@ def _check_chunk_receiving(self, chunk_id, chunk_no): filelog.error(f"Error: chunked file transfer f{chunk_id} timed out") self.receive_chunks_in_progress.pop(chunk_id, None) - def cancel_download(self, send_id, message="Cancelled"): + def cancel_download(self, send_id:str, message="Cancelled"): filelog("cancel_download(%s, %s)", send_id, message) for chunk_id, chunk_state in dict(self.receive_chunks_in_progress).items(): if chunk_state.send_id==send_id: @@ -339,7 +340,7 @@ def cancel_download(self, send_id, message="Cancelled"): return filelog.error("Error: cannot cancel download %s, entry not found!", u(send_id)) - def cancel_file(self, chunk_id, message, chunk=0): + def cancel_file(self, chunk_id:int, message:str, chunk:int=0): filelog("cancel_file%s", (chunk_id, message, chunk)) chunk_state = self.receive_chunks_in_progress.get(chunk_id) if chunk_state: @@ -451,7 +452,7 @@ def progress(position, error=None): self.process_downloaded_file(filename, chunk_state.mimetype, chunk_state.printit, chunk_state.openit, chunk_state.filesize, options) - def accept_data(self, send_id, dtype, basefilename, printit, openit): + def accept_data(self, send_id:str, dtype, basefilename:str, printit:bool, openit:bool): #subclasses should check the flags, #and if ask is True, verify they have accepted this specific send_id filelog("accept_data%s", (send_id, dtype, basefilename, printit, openit)) @@ -586,7 +587,7 @@ def process_downloaded_file(self, filename, mimetype, printit, openit, filesize, args=(filename, mimetype, printit, openit, filesize, options)) filelog("started process-download thread: %s", t) - def do_process_downloaded_file(self, filename, mimetype, printit, openit, filesize, options): + def do_process_downloaded_file(self, filename:str, mimetype:str, printit:bool, openit:bool, filesize:int, options): filelog("do_process_downloaded_file%s", (filename, mimetype, printit, openit, filesize, options)) if printit: self._print_file(filename, mimetype, options) @@ -599,7 +600,7 @@ def do_process_downloaded_file(self, filename, mimetype, printit, openit, filesi return self._open_file(filename) - def _print_file(self, filename, mimetype, options): + def _print_file(self, filename:str, mimetype:str, options): printlog("print_file%s", (filename, mimetype, options)) printer = options.strget("printer") title = options.strget("title") @@ -658,17 +659,17 @@ def check_printing_finished(): self.timeout_add(10000, check_printing_finished) - def get_open_env(self): + def get_open_env(self) -> Dict[str,str]: env = os.environ.copy() #prevent loops: env["XPRA_XDG_OPEN"] = "1" return env - def _open_file(self, url): + def _open_file(self, url:str): filelog("_open_file(%s)", url) self.exec_open_command(url) - def _open_url(self, url): + def _open_url(self, url:str): filelog("_open_url(%s)", url) if POSIX: #we can't use webbrowser, @@ -679,7 +680,7 @@ def _open_url(self, url): import webbrowser #pylint: disable=import-outside-toplevel webbrowser.open_new_tab(url) - def exec_open_command(self, url): + def exec_open_command(self, url:str): filelog("exec_open_command(%s)", url) try: import shlex #pylint: disable=import-outside-toplevel @@ -704,12 +705,12 @@ def open_done(*_args): cr = getChildReaper() cr.add_process(proc, f"Open file {url}", command, True, True, open_done) - def file_size_warning(self, action, location, basefilename, filesize, limit): + def file_size_warning(self, action:str, location:str, basefilename:str, filesize:int, limit:int): filelog.warn("Warning: cannot %s the file '%s'", action, basefilename) filelog.warn(" this file is too large: %sB", std_unit(filesize)) filelog.warn(" the %s file size limit is %sB", location, std_unit(limit)) - def check_file_size(self, action, filename, filesize): + def check_file_size(self, action:str, filename:str, filesize:int): basefilename = os.path.basename(filename) if filesize>self.file_size_limit: self.file_size_warning(action, "local", basefilename, filesize, self.file_size_limit) @@ -720,7 +721,7 @@ def check_file_size(self, action, filename, filesize): return True - def send_request_file(self, filename, openit=True): + def send_request_file(self, filename:str, openit:bool=True): self.send("request-file", filename, openit) self.files_requested[filename] = openit @@ -738,7 +739,7 @@ def _process_open_url(self, packet): filelog("url '%s' not accepted", url) - def send_open_url(self, url): + def send_open_url(self, url:str): if not self.remote_open_url: filelog.warn("Warning: remote end does not accept URLs") return False @@ -748,7 +749,7 @@ def send_open_url(self, url): self.do_send_open_url(url) return True - def do_send_open_url(self, url, send_id=""): + def do_send_open_url(self, url:str, send_id:str=""): self.send("open-url", url, send_id) def send_file(self, filename, mimetype, data, filesize=0, @@ -796,7 +797,7 @@ def send_file(self, filename, mimetype, data, filesize=0, return True def send_data_request(self, action, dtype, url, mimetype="", data="", filesize=0, - printit=False, openit=True, options=None): + printit=False, openit=True, options=None) -> Optional[str]: send_id = uuid.uuid4().hex if len(self.pending_send_data)>=MAX_CONCURRENT_FILES: filelog.warn("Warning: %s dropped", action) @@ -812,7 +813,7 @@ def send_data_request(self, action, dtype, url, mimetype="", data="", filesize=0 return send_id - def _process_send_data_request(self, packet): + def _process_send_data_request(self, packet) -> None: dtype, send_id, url, _, filesize, printit, openit = packet[1:8] options = {} if len(packet)>=9: @@ -824,7 +825,7 @@ def _process_send_data_request(self, packet): self.do_process_send_data_request(dtype, send_id, url, _, filesize, printit, openit, typedict(options)) - def do_process_send_data_request(self, dtype, send_id, url, _, filesize, printit, openit, options): + def do_process_send_data_request(self, dtype, send_id, url, _, filesize, printit, openit, options) -> None: filelog("do_process_send_data_request: send_id=%s, url=%s, printit=%s, openit=%s, options=%s", u(send_id), url, printit, openit, options) def cb_answer(accept): @@ -869,13 +870,14 @@ def cb_answer(accept): else: self.ask_data_request(cb_answer, send_id, dtype, url, filesize, printit, openit) - def ask_data_request(self, cb_answer, send_id, dtype, url, filesize, printit, openit): + def ask_data_request(self, cb_answer:Callable, send_id:str, dtype:str, url:str, filesize:int, + printit:bool, openit:bool) -> None: #subclasses may prompt the user here instead filelog("ask_data_request%s", (send_id, dtype, url, filesize, printit, openit)) v = self.accept_data(send_id, dtype, url, printit, openit) cb_answer(v) - def _process_send_data_response(self, packet): + def _process_send_data_response(self, packet) -> None: send_id, accept = packet[1:3] send_id = net_utf8(send_id) filelog("process send-data-response: send_id=%s, accept=%s", send_id, accept) @@ -911,7 +913,7 @@ def _process_send_data_response(self, packet): else: filelog.error("Error: unknown datatype '%s'", dtype) - def send_data_ask_timeout(self, send_id): + def send_data_ask_timeout(self, send_id) -> bool: v = self.pending_send_data.pop(send_id, None) self.pending_send_data_timers.pop(send_id, None) if not v: @@ -923,7 +925,8 @@ def send_data_ask_timeout(self, send_id): filelog.warn(" the send approval request timed out") return False - def do_send_file(self, filename, mimetype, data, filesize=0, printit=False, openit=False, options=None, send_id=""): + def do_send_file(self, filename:str, mimetype:str, data, filesize:int=0, + printit:bool=False, openit:bool=False, options=None, send_id:str="") -> bool: if printit: action = "print" l = printlog @@ -963,7 +966,7 @@ def do_send_file(self, filename, mimetype, data, filesize=0, printit=False, open self.send("send-file", basefilename, mimetype, printit, openit, filesize, cdata, options, send_id) return True - def _check_chunk_sending(self, chunk_id, chunk_no): + def _check_chunk_sending(self, chunk_id:str, chunk_no:int) -> None: chunk_state = self.send_chunks_in_progress.get(chunk_id) filelog("_check_chunk_sending(%s, %s) chunk_state found: %s", chunk_id, chunk_no, bool(chunk_state)) if not chunk_state: @@ -975,7 +978,7 @@ def _check_chunk_sending(self, chunk_id, chunk_no): filelog.error(f" on chunk {chunk_no}") self.cancel_sending(chunk_id) - def cancel_sending(self, chunk_id): + def cancel_sending(self, chunk_id:str) -> None: chunk_state = self.send_chunks_in_progress.pop(chunk_id, None) filelog("cancel_sending(%s) chunk state found: %s", chunk_id, bool(chunk_state)) if not chunk_state: @@ -985,7 +988,7 @@ def cancel_sending(self, chunk_id): chunk_state.timer = 0 self.source_remove(timer) - def _process_ack_file_chunk(self, packet): + def _process_ack_file_chunk(self, packet) -> None: #the other end received our send-file or send-file-chunk, #send some more file data filelog("ack-file-chunk: %s", packet[1:]) @@ -1023,12 +1026,12 @@ def _process_ack_file_chunk(self, packet): chunk_state.timer = self.timeout_add(CHUNK_TIMEOUT, self._check_chunk_sending, chunk_id, chunk) self.send("send-file-chunk", chunk_id, chunk, cdata, bool(chunk_state.data)) - def send(self, *parts): + def send(self, *parts) -> None: raise NotImplementedError() def compressed_wrapper(self, datatype, data, level=5): raise NotImplementedError() - def transfer_progress_update(self, send=True, transfer_id=0, elapsed=0, position=0, total=0, error=None): + def transfer_progress_update(self, send=True, transfer_id=0, elapsed=0, position=0, total=0, error=None) -> None: #this method is overridden in the gtk client: filelog("transfer_progress_update%s", (send, transfer_id, elapsed, position, total, error)) diff --git a/xpra/net/mdns/avahi_publisher.py b/xpra/net/mdns/avahi_publisher.py index 88ba83dee8..640e6f97e5 100755 --- a/xpra/net/mdns/avahi_publisher.py +++ b/xpra/net/mdns/avahi_publisher.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # This file is part of Xpra. -# Copyright (C) 2013-2019 Antoine Martin +# Copyright (C) 2013-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -137,11 +137,11 @@ def iface(self): return "interface %i" % self.interface return "all interfaces" - def get_info(self) -> dict: + def host_str(self) -> str: return "%s %s:%s on %s" % (self.name, self.host, self.port, self.iface()) def __repr__(self): - return "AvahiPublisher(%s)" % self.get_info() + return "AvahiPublisher(%s)" % self.host_str() def start(self): try: @@ -195,7 +195,7 @@ def add_service(self): #use try+except as older versions may not have those modules? message = e.get_dbus_message() dbus_error_name = e.get_dbus_name() - log.error("Error starting publisher %s", self.get_info()) + log.error("Error starting publisher %s", self.host_str()) if dbus_error_name=="org.freedesktop.Avahi.CollisionError": log.error(" another instance already claims this dbus name") log.estr(e) diff --git a/xpra/net/net_util.py b/xpra/net/net_util.py index df467daf69..806f27147d 100755 --- a/xpra/net/net_util.py +++ b/xpra/net/net_util.py @@ -347,7 +347,7 @@ def parsenums(v): addproc(f"/proc/sys/net/ipv4/{k}", "ipv4", k, int) return net_sys_config -def get_net_config() -> dict: +def get_net_config() -> Dict[str,Any]: config = {} try: from xpra.net.bytestreams import VSOCK_TIMEOUT, SOCKET_TIMEOUT, SOCKET_NODELAY # pylint: disable=import-outside-toplevel @@ -402,7 +402,7 @@ def get_ssl_info(show_constants=False) -> Dict[str,Any]: return info -def get_network_caps(full_info : int=1) -> dict: +def get_network_caps(full_info : int=1) -> Dict[str,Any]: # pylint: disable=import-outside-toplevel from xpra.net.digest import get_digests from xpra.net.compression import get_enabled_compressors, get_compression_caps @@ -422,7 +422,7 @@ def get_network_caps(full_info : int=1) -> dict: return caps -def get_info() -> dict: +def get_info() -> Dict[str,Any]: i = get_network_caps() netifaces = import_netifaces() if netifaces: diff --git a/xpra/net/protocol/socket_handler.py b/xpra/net/protocol/socket_handler.py index 869e186c46..4d145ccd0a 100644 --- a/xpra/net/protocol/socket_handler.py +++ b/xpra/net/protocol/socket_handler.py @@ -1,5 +1,5 @@ # This file is part of Xpra. -# Copyright (C) 2011-2022 Antoine Martin +# Copyright (C) 2011-2023 Antoine Martin # Copyright (C) 2008, 2009, 2010 Nathaniel Smith # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -14,6 +14,7 @@ from socket import error as socket_error from threading import Lock, RLock, Event from queue import Queue +from typing import Dict, Any from xpra.os_util import memoryview_to_bytes, strtobytes, bytestostr, hexstr from xpra.util import repr_ellipsized, ellipsizer, csv, envint, envbool, typedict @@ -235,7 +236,7 @@ def parse_remote_caps(self, caps : typedict): def set_receive_aliases(self, aliases): self.receive_aliases = aliases - def get_info(self, alias_info=True) -> dict: + def get_info(self, alias_info:bool=True) -> Dict[str,Any]: shm = self._source_has_more info = { "large_packets" : self.large_packets, diff --git a/xpra/net/quic/connection.py b/xpra/net/quic/connection.py index 2780207863..180af55a30 100644 --- a/xpra/net/quic/connection.py +++ b/xpra/net/quic/connection.py @@ -5,7 +5,7 @@ import os from queue import Queue -from typing import Callable, Union +from typing import Callable, Union, Dict, Any from aioquic.h0.connection import H0Connection from aioquic.h3.connection import H3Connection @@ -44,7 +44,7 @@ def __init__(self, connection: HttpConnection, stream_id: int, transmit: Callabl def __repr__(self): return f"XpraQuicConnection<{self.stream_id}>" - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = super().get_info() qinfo = info.setdefault("quic", {}) quic = getattr(self.connection, "_quic", None) diff --git a/xpra/net/quic/websocket.py b/xpra/net/quic/websocket.py index 51b4e7027b..81d828312c 100644 --- a/xpra/net/quic/websocket.py +++ b/xpra/net/quic/websocket.py @@ -4,7 +4,7 @@ # later version. See the file COPYING for details. import os -from typing import Callable, Dict +from typing import Callable, Dict, Any from aioquic.h3.events import HeadersReceived, H3Event from aioquic.h3.exceptions import NoAvailablePushIDError @@ -28,7 +28,7 @@ def __init__(self, connection, scope: Dict, self._packet_type_streams = {} self._use_substreams = bool(SUBSTREAM_PACKET_TYPES) - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = super().get_info() info.setdefault("quic", {})["scope"] = self.scope return info @@ -56,7 +56,7 @@ def http_event_received(self, event: H3Event) -> None: return super().http_event_received(event) - def send_accept(self, stream_id : int): + def send_accept(self, stream_id : int) -> None: self.send_headers(stream_id=stream_id, headers={ ":status" : 200, "server" : SERVER_NAME, diff --git a/xpra/net/socket_util.py b/xpra/net/socket_util.py index 437093b135..16e338746d 100644 --- a/xpra/net/socket_util.py +++ b/xpra/net/socket_util.py @@ -1,5 +1,5 @@ # This file is part of Xpra. -# Copyright (C) 2017-2022 Antoine Martin +# Copyright (C) 2017-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -7,6 +7,7 @@ import socket from time import sleep, monotonic from ctypes import Structure, c_uint8, sizeof +from typing import Callable, Optional, Dict, Any from xpra.common import GROUP from xpra.scripts.config import InitException, InitExit, TRUE_OPTIONS @@ -121,7 +122,7 @@ def hosts(host_str): return ["0.0.0.0", "::"] return [host_str] -def add_listen_socket(socktype, sock, info, server, new_connection_cb, options=None): +def add_listen_socket(socktype, sock, info, server, new_connection_cb, options=None) -> Optional[Callable]: log = get_network_logger() log("add_listen_socket%s", (socktype, sock, info, server, new_connection_cb, options)) try: @@ -896,7 +897,7 @@ def mdns_publish(display_name, listen_on, text_dict=None): "options", "ciphers", ) -def get_ssl_attributes(opts, server_side=True, overrides=None) -> dict: +def get_ssl_attributes(opts, server_side=True, overrides=None) -> Dict[str,Any]: args = { "server-side" : server_side, } @@ -909,7 +910,7 @@ def get_ssl_attributes(opts, server_side=True, overrides=None) -> dict: args[attr] = v return args -def find_ssl_cert(filename="ssl-cert.pem"): +def find_ssl_cert(filename:str="ssl-cert.pem"): from xpra.log import Logger ssllog = Logger("ssl") #try to locate the cert file from known locations @@ -942,7 +943,7 @@ def ssl_wrap_socket(sock, **kwargs): ssllog("ssl_wrap_socket(%s, %s) context=%s, wrap_kwargs=%s", sock, kwargs, context, wrap_kwargs) return do_wrap_socket(sock, context, **wrap_kwargs) -def log_ssl_info(ssl_sock): +def log_ssl_info(ssl_sock) -> None: from xpra.log import Logger ssllog = Logger("ssl") ssllog("server_hostname=%s", ssl_sock.server_hostname) @@ -964,7 +965,7 @@ def log_ssl_info(ssl_sock): SSL_VERIFY_UNTRUSTED_ROOT = 19 SSL_VERIFY_IP_MISMATCH = 64 SSL_VERIFY_HOSTNAME_MISMATCH = 62 -SSL_VERIFY_CODES = { +SSL_VERIFY_CODES : Dict[int,str] = { SSL_VERIFY_EXPIRED : "expired", #also revoked! SSL_VERIFY_WRONG_HOST : "wrong host", SSL_VERIFY_SELF_SIGNED : "self-signed", @@ -1255,7 +1256,7 @@ def confirm(*args): return options return None -def load_ssl_options(server_hostname, port): +def load_ssl_options(server_hostname, port) -> Dict[str,Any]: from xpra.log import Logger ssllog = Logger("ssl") f = find_ssl_config_file(server_hostname, port, "options") @@ -1283,7 +1284,7 @@ def load_ssl_options(server_hostname, port): ssllog("load_ssl_options%s=%s (from %r)", (server_hostname, port), options, f) return options -def save_ssl_options(server_hostname, port=443, options=b""): +def save_ssl_options(server_hostname:str, port=443, options=b"") -> Optional[str]: from xpra.log import Logger ssllog = Logger("ssl") boptions = b"\n".join(("%s=%s" % (k.replace("_", "-"), v)).encode("latin1") for k, v in options.items()) @@ -1293,7 +1294,7 @@ def save_ssl_options(server_hostname, port=443, options=b""): ssllog("save_ssl_options%s saved to %r", (server_hostname, port, options), f) return f -def find_ssl_config_file(server_hostname, port=443, filename="cert.pem"): +def find_ssl_config_file(server_hostname:str, port=443, filename="cert.pem"): from xpra.log import Logger ssllog = Logger("ssl") from xpra.platform.paths import get_ssl_hosts_config_dirs @@ -1308,7 +1309,7 @@ def find_ssl_config_file(server_hostname, port=443, filename="cert.pem"): return f return None -def save_ssl_config_file(server_hostname, port=443, filename="cert.pem", fileinfo="certificate", filedata=b""): +def save_ssl_config_file(server_hostname:str, port=443, filename="cert.pem", fileinfo="certificate", filedata=b""): from xpra.log import Logger ssllog = Logger("ssl") from xpra.platform.paths import get_ssl_hosts_config_dirs diff --git a/xpra/net/ssh/paramiko_client.py b/xpra/net/ssh/paramiko_client.py index 50feec9f47..ef1c86ea33 100644 --- a/xpra/net/ssh/paramiko_client.py +++ b/xpra/net/ssh/paramiko_client.py @@ -8,6 +8,7 @@ import re import socket from time import sleep, monotonic +from typing import Dict, Any from xpra.scripts.main import ( InitException, InitExit, @@ -103,12 +104,12 @@ def peek(self, n): return None return self._raw_socket.recv(n, socket.MSG_PEEK) - def get_socket_info(self) -> dict: + def get_socket_info(self) -> Dict[str,Any]: if not self._raw_socket: return {} return self.do_get_socket_info(self._raw_socket) - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: i = super().get_info() s = self._socket if s: @@ -133,7 +134,7 @@ def error_is_closed(self, e) -> bool: return True return super().error_is_closed(e) - def get_socket_info(self) -> dict: + def get_socket_info(self) -> Dict[str,Any]: p = self.process if not p: return {} diff --git a/xpra/net/subprocess_wrapper.py b/xpra/net/subprocess_wrapper.py index 3e11c9e1fd..fcc58e8b49 100644 --- a/xpra/net/subprocess_wrapper.py +++ b/xpra/net/subprocess_wrapper.py @@ -1,5 +1,5 @@ # This file is part of Xpra. -# Copyright (C) 2015-2020 Antoine Martin +# Copyright (C) 2015-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -7,6 +7,7 @@ import sys import subprocess from queue import Queue +from typing import Dict, Any from xpra.gtk_common.gobject_compat import register_os_signals from xpra.util import repr_ellipsized, envint, envbool, csv @@ -290,7 +291,7 @@ def process_packet(self, proto, packet): INJECT_FAULT(proto) -def exec_kwargs() -> dict: +def exec_kwargs() -> Dict[str,Any]: kwargs = {} stderr = sys.stderr.fileno() if WIN32: @@ -307,7 +308,7 @@ def exec_kwargs() -> dict: kwargs["stderr"] = stderr return kwargs -def exec_env(blacklist=("LS_COLORS", )) -> dict: +def exec_env(blacklist=("LS_COLORS", )) -> Dict[str,str]: env = os.environ.copy() env["XPRA_SKIP_UI"] = "1" env["XPRA_FORCE_COLOR_LOG"] = "1" diff --git a/xpra/notifications/dbus_notifier.py b/xpra/notifications/dbus_notifier.py index fabe116f64..66eb254032 100644 --- a/xpra/notifications/dbus_notifier.py +++ b/xpra/notifications/dbus_notifier.py @@ -1,9 +1,10 @@ # This file is part of Xpra. -# Copyright (C) 2011-2019 Antoine Martin +# Copyright (C) 2011-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import os +from typing import Dict from xpra.util import ellipsizer, csv from xpra.os_util import bytestostr @@ -108,10 +109,10 @@ def _find_nid(self, actual_id : int): return k return None - def noparse_hints(self, h) -> dict: + def noparse_hints(self, h) -> Dict: return h - def parse_hints(self, h) -> dict: + def parse_hints(self, h) -> Dict: hints = {} for x in ("action-icons", "category", "desktop-entry", "resident", "transient", "x", "y", "urgency"): v = h.get(x) diff --git a/xpra/os_util.py b/xpra/os_util.py index e630d21d80..5d6dd24577 100644 --- a/xpra/os_util.py +++ b/xpra/os_util.py @@ -325,7 +325,7 @@ def restore_script_env(env): _saved_env = os.environ.copy() -def get_saved_env() -> dict: +def get_saved_env() -> Dict[str,str]: return _saved_env.copy() def get_saved_env_var(var, default=None): diff --git a/xpra/platform/darwin/osx_clipboard.py b/xpra/platform/darwin/osx_clipboard.py index 5d22e39731..53ad831a3d 100644 --- a/xpra/platform/darwin/osx_clipboard.py +++ b/xpra/platform/darwin/osx_clipboard.py @@ -178,7 +178,7 @@ def get_image_contents(self, target): return img_data - def got_token(self, targets, target_data=None, claim=True, _synchronous_client=False): + def got_token(self, targets, target_data=None, claim=True, _synchronous_client=False) -> None: # the remote end now owns the clipboard self.cancel_emit_token() if not self._enabled: diff --git a/xpra/platform/darwin/shadow_server.py b/xpra/platform/darwin/shadow_server.py index fc9c8f7f20..a65d6bdead 100644 --- a/xpra/platform/darwin/shadow_server.py +++ b/xpra/platform/darwin/shadow_server.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2013-2020 Antoine Martin +# Copyright (C) 2013-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. +from typing import Dict, Any, List + import Quartz.CoreGraphics as CG #@UnresolvedImport from xpra.util import envbool @@ -11,6 +13,7 @@ from xpra.scripts.config import InitExit from xpra.scripts.main import check_display from xpra.exit_codes import ExitCode +from xpra.codecs.image_wrapper import ImageWrapper from xpra.server.gtk_server_base import GTKServerBase from xpra.server.shadow.gtk_shadow_server_base import GTKShadowServerBase from xpra.platform.darwin.keyboard_config import KeyboardConfig @@ -22,7 +25,7 @@ USE_TIMER = envbool("XPRA_OSX_SHADOW_USE_TIMER", False) -ALPHA = { +ALPHA : Dict[int,str] = { CG.kCGImageAlphaNone : "AlphaNone", CG.kCGImageAlphaPremultipliedLast : "PremultipliedLast", CG.kCGImageAlphaPremultipliedFirst : "PremultipliedFirst", @@ -35,7 +38,7 @@ BTYPES = tuple((str, bytes, memoryview, bytearray)) #ensure that picture_encode can deal with pixels as NSCFData: -def patch_pixels_to_bytes(): +def patch_pixels_to_bytes() -> None: from CoreFoundation import CFDataGetBytes, CFDataGetLength #@UnresolvedImport def pixels_to_bytes(v): if isinstance(v, BTYPES): @@ -51,20 +54,20 @@ class OSXRootCapture: def __repr__(self): return "OSXRootCapture" - def get_type(self): + def get_type(self) -> str: return "CoreGraphics" - def refresh(self): + def refresh(self) -> bool: return True - def clean(self): + def clean(self) -> None: """ nothing specific to do here on MacOS """ - def get_image(self, x, y, width, height): + def get_image(self, x, y, width, height) -> ImageWrapper: rect = (x, y, width, height) return get_CG_imagewrapper(rect) - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return { "type" : "CoreGraphics", } @@ -93,13 +96,13 @@ def __init__(self, display=None, multi_window=True): self.refresh_registered = False super().__init__() - def init(self, opts): + def init(self, opts) -> None: super().init(opts) self.keycodes = {} #printing fails silently on OSX self.printing = False - def get_keyboard_config(self, _props=None): + def get_keyboard_config(self, _props=None) -> KeyboardConfig: return KeyboardConfig() def make_tray_widget(self): @@ -108,10 +111,10 @@ def make_tray_widget(self): self.tray_click_callback, mouseover_cb=None, exit_cb=self.tray_exit_callback) - def setup_capture(self): + def setup_capture(self) -> OSXRootCapture: return OSXRootCapture() - def screen_refresh_callback(self, count, rects, info): + def screen_refresh_callback(self, count, rects, info) -> None: log("screen_refresh_callback%s mapped=%s", (count, rects, info), self.mapped) self.refresh_count += 1 rlist = [] @@ -124,7 +127,7 @@ def screen_refresh_callback(self, count, rects, info): #return quickly, and process the list copy via idle add: self.idle_add(self.do_screen_refresh, rlist) - def do_screen_refresh(self, rlist): + def do_screen_refresh(self, rlist:List) -> None: #TODO: improve damage method to handle lists directly: from xpra.rectangle import rectangle #@UnresolvedImport model_rects = {} @@ -139,7 +142,7 @@ def do_screen_refresh(self, rlist): ry = mrect.y-rect.y self.refresh_window_area(model, rx, ry, mrect.width, mrect.height, {"damage" : True}) - def start_refresh(self, wid): + def start_refresh(self, wid:int) -> None: #don't use the timer, get damage notifications: if wid not in self.mapped: self.mapped.append(wid) @@ -155,7 +158,7 @@ def start_refresh(self, wid): log.warn(" using fallback timer method") super().start_refresh(wid) - def stop_refresh(self, wid): + def stop_refresh(self, wid:int) -> None: log("stop_refresh(%i) mapped=%s, timer=%s", wid, self.mapped, self.refresh_timer) #may stop the timer fallback: super().stop_refresh(wid) @@ -171,14 +174,14 @@ def stop_refresh(self, wid): self.refresh_registered = False - def do_process_mouse_common(self, proto, device_id, wid, pointer, props): + def do_process_mouse_common(self, proto, device_id:int, wid:int, pointer, props) -> bool: if proto not in self._server_sources: return False assert wid in self._id_to_window CG.CGWarpMouseCursorPosition(pointer[:2]) return True - def fake_key(self, keycode, press): + def fake_key(self, keycode:int, press:bool) -> None: e = CG.CGEventCreateKeyboardEvent(None, keycode, press) log("fake_key(%s, %s)", keycode, press) #CGEventSetFlags(keyPress, modifierFlags) @@ -187,14 +190,14 @@ def fake_key(self, keycode, press): #this causes crashes, don't do it! #CG.CFRelease(e) - def do_process_button_action(self, proto, device_id, wid, button, pressed, pointer, props): + def do_process_button_action(self, proto, device_id:int, wid:int, button:int, pressed:bool, pointer, props): if "modifiers" in props: self._update_modifiers(proto, wid, props.get("modifiers")) pointer = self._process_mouse_common(proto, device_id, wid, pointer) if pointer: self.button_action(device_id, wid, pointer, button, pressed, props) - def button_action(self, device_id, wid, pointer, button, pressed, props): + def button_action(self, device_id:int, wid:int, pointer, button:int, pressed:bool, props): if button<=3: #we should be using CGEventCreateMouseEvent #instead we clear previous clicks when a "higher" button is pressed... oh well @@ -219,13 +222,13 @@ def button_action(self, device_id, wid, pointer, button, pressed, props): r = CG.CGPostScrollWheelEvent(*event) log("CG.CGPostScrollWheelEvent%s=%s", event, r) - def make_hello(self, source): + def make_hello(self, source) -> Dict[str,Any]: capabilities = GTKServerBase.make_hello(self, source) capabilities["shadow"] = True capabilities["server_type"] = "Python/gtk2/osx-shadow" return capabilities - def get_info(self, proto, *_args): + def get_info(self, proto, *_args) -> Dict[str,Any]: info = GTKServerBase.get_info(self, proto) info.setdefault("features", {})["shadow"] = True info.setdefault("server", {})["type"] = "Python/gtk2/osx-shadow" diff --git a/xpra/platform/gui.py b/xpra/platform/gui.py index 321e107051..6dddaa1fff 100755 --- a/xpra/platform/gui.py +++ b/xpra/platform/gui.py @@ -1,13 +1,14 @@ #!/usr/bin/env python3 # This file is part of Xpra. # Copyright (C) 2010 Nathaniel Smith -# Copyright (C) 2012-2021 Antoine Martin +# Copyright (C) 2012-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import os import sys import binascii +from typing import Dict, Any from xpra.platform import platform_import from xpra.os_util import bytestostr @@ -117,7 +118,7 @@ def get_display_icc_info(): #per display info return {} -def get_icc_info(): +def get_icc_info() -> Dict[str,Any]: return default_get_icc_info() def default_get_icc_info(): diff --git a/xpra/platform/posix/webcam.py b/xpra/platform/posix/webcam.py index d0dfe3937a..7a677fcbbb 100644 --- a/xpra/platform/posix/webcam.py +++ b/xpra/platform/posix/webcam.py @@ -1,10 +1,11 @@ # This file is part of Xpra. -# Copyright (C) 2016-2019 Antoine Martin +# Copyright (C) 2016-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. #pylint: disable-msg=E1101 import os +from typing import Dict from xpra.util import envbool from xpra.os_util import is_Ubuntu, is_Debian @@ -50,7 +51,7 @@ def query_video_device(device): return {} -def get_virtual_video_devices(capture_only=True) -> dict: +def get_virtual_video_devices(capture_only=True) -> Dict[int, Dict]: log(f"get_virtual_video_devices({capture_only}) CHECK_VIRTUAL_CAPTURE={CHECK_VIRTUAL_CAPTURE}") if not check_virtual_dir(False): return {} diff --git a/xpra/platform/win32/clipboard.py b/xpra/platform/win32/clipboard.py index 9bc8f50c23..0c6bfc1e62 100644 --- a/xpra/platform/win32/clipboard.py +++ b/xpra/platform/win32/clipboard.py @@ -490,7 +490,7 @@ def got_clipboard_lock(): self.with_clipboard_lock(got_clipboard_lock, errback) - def got_token(self, targets, target_data=None, claim=True, _synchronous_client=False): + def got_token(self, targets, target_data=None, claim=True, _synchronous_client=False) -> None: # the remote end now owns the clipboard self.cancel_emit_token() if not self._enabled: diff --git a/xpra/platform/win32/gdi_screen_capture.py b/xpra/platform/win32/gdi_screen_capture.py index aa323f378b..e28487b095 100644 --- a/xpra/platform/win32/gdi_screen_capture.py +++ b/xpra/platform/win32/gdi_screen_capture.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2012-2019 Antoine Martin +# Copyright (C) 2012-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -10,6 +10,7 @@ Structure, create_string_buffer, addressof, byref, c_ubyte, ) from io import BytesIO +from typing import Dict, Any, List, Tuple, Optional from PIL import Image from xpra.log import Logger @@ -32,7 +33,7 @@ NULLREGION = 1 #The region is empty. SIMPLEREGION = 2 #The region is a single rectangle. COMPLEXREGION = 3 #The region is more than a single rectangle. -REGION_CONSTS = { +REGION_CONSTS : Dict[int,str] = { NULLREGION : "the region is empty", SIMPLEREGION : "the region is a single rectangle", COMPLEXREGION : "the region is more than a single rectangle", @@ -49,7 +50,7 @@ class PALETTEENTRY(Structure): DWM_EC_DISABLECOMPOSITION = 0 DWM_EC_ENABLECOMPOSITION = 1 -def set_dwm_composition(value=DWM_EC_DISABLECOMPOSITION): +def set_dwm_composition(value=DWM_EC_DISABLECOMPOSITION) -> bool: try: windll.dwmapi.DwmEnableComposition(value) log("DwmEnableComposition(%s) succeeded", value) @@ -59,7 +60,7 @@ def set_dwm_composition(value=DWM_EC_DISABLECOMPOSITION): log.estr(e) return False -def get_desktop_bit_depth(): +def get_desktop_bit_depth() -> int: desktop_wnd = GetDesktopWindow() dc = GetWindowDC(desktop_wnd) assert dc, "failed to get a drawing context from the desktop window %s" % desktop_wnd @@ -68,7 +69,7 @@ def get_desktop_bit_depth(): ReleaseDC(desktop_wnd, dc) return bit_depth -def get_palette(dc): +def get_palette(dc) -> List: count = GetSystemPaletteEntries(dc, 0, 0, None) log("palette size: %s", count) palette = [] @@ -103,24 +104,24 @@ def __init__(self): def __repr__(self): return "GDICapture(%i-bits)" % self.bit_depth - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return { "type" : "gdi", "depth" : self.bit_depth, } - def get_type(self): + def get_type(self) -> str: return "GDI" def refresh(self) -> bool: return True - def clean(self): + def clean(self) -> None: if self.disabled_dwm_composition: set_dwm_composition(DWM_EC_ENABLECOMPOSITION) self.clean_dc() - def clean_dc(self): + def clean_dc(self) -> None: dc = self.dc wnd = self.wnd if dc and wnd: @@ -132,7 +133,7 @@ def clean_dc(self): self.memdc = None DeleteDC(memdc) - def get_capture_coords(self, x, y, width, height): + def get_capture_coords(self, x:int, y:int, width:int, height:int) -> Tuple[int,int,int,int]: metrics = get_virtualscreenmetrics() if self.metrics is None or self.metrics!=metrics: #new metrics, start from scratch: @@ -157,7 +158,7 @@ def get_capture_coords(self, x, y, width, height): height = dh return x, y, width, height - def get_image(self, x=0, y=0, width=0, height=0): + def get_image(self, x:int=0, y:int=0, width:int=0, height:int=0) -> Optional[ImageWrapper]: start = time.time() x, y, width, height = self.get_capture_coords(x, y, width, height) if not self.dc: @@ -231,7 +232,7 @@ def get_image(self, x=0, y=0, width=0, height=0): log("get_image%s=%s took %ims", (x, y, width, height), v, (time.time()-start)*1000) return v - def take_screenshot(self): + def take_screenshot(self) -> Tuple: x, y, w, h = get_virtualscreenmetrics() image = self.get_image(x, y, w, h) if not image: diff --git a/xpra/platform/win32/namedpipes/connection.py b/xpra/platform/win32/namedpipes/connection.py index 0eedd7e251..e1b18538dd 100644 --- a/xpra/platform/win32/namedpipes/connection.py +++ b/xpra/platform/win32/namedpipes/connection.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # This file is part of Xpra. -# Copyright (c) 2016-2017 Antoine Martin +# Copyright (c) 2016-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -10,6 +10,7 @@ import errno from ctypes import addressof, byref, c_ulong, c_char_p, c_char, c_void_p, cast, string_at from ctypes.wintypes import DWORD +from typing import Dict, Any from xpra.os_util import strtobytes, memoryview_to_bytes from xpra.net.bytestreams import Connection @@ -185,7 +186,7 @@ def logerr(fn, *args): def __repr__(self): return self.target - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: d = super().get_info() d["type"] = "named-pipe" d["closed"] = self.pipe_handle is None diff --git a/xpra/platform/win32/win32_notifier.py b/xpra/platform/win32/win32_notifier.py index bc110e0eee..f298eb4c62 100644 --- a/xpra/platform/win32/win32_notifier.py +++ b/xpra/platform/win32/win32_notifier.py @@ -4,17 +4,18 @@ # later version. See the file COPYING for details. import sys +from typing import Optional, Type from xpra.util import envbool from xpra.notifications.notifier_base import NotifierBase, log from xpra.platform.win32.win32_balloon import notify -try: - from xpra.gtk_common.gtk_notifier import GTK_Notifier - GTK_NOTIFIER = envbool("XPRA_WIN32_GTK_NOTIFIER", False) -except ImportError: - GTK_Notifier = None - GTK_NOTIFIER = False +GTK_NOTIFIER = envbool("XPRA_WIN32_GTK_NOTIFIER", False) +if GTK_NOTIFIER: + try: + from xpra.gtk_common.gtk_notifier import GTK_Notifier + except ImportError: + GTK_NOTIFIER = False def do_notify(*args): @@ -30,13 +31,13 @@ class Win32_Notifier(NotifierBase): def __init__(self, *args): super().__init__(*args) - self.handles_actions = GTK_Notifier is not None + self.handles_actions = GTK_NOTIFIER self.gtk_notifier = None self.gtk_notifications = set() self.notification_handles = {} def get_gtk_notifier(self): - if self.gtk_notifier is None: + if self.gtk_notifier is None and GTK_NOTIFIER: try: self.gtk_notifier = GTK_Notifier(self.closed_cb, self.action_cb) except Exception: diff --git a/xpra/scripts/config.py b/xpra/scripts/config.py index 5791d4b05d..e134e487da 100755 --- a/xpra/scripts/config.py +++ b/xpra/scripts/config.py @@ -309,7 +309,7 @@ def save_config(conf_file:str, config, keys, extras_types=None): f.write(f"{key}={v}{os.linesep}") debug(f"save_config: saved {saved} to {conf_file!r}") -def read_config(conf_file:str) -> Dict: +def read_config(conf_file:str) -> Dict[str,Any]: """ Parses a config file into a dict of strings. If the same key is specified more than once, @@ -1180,7 +1180,7 @@ def print_bool(k, v, true_str='yes', false_str='no') -> str: def parse_bool_or_int(k, v) -> Union[int,bool]: return parse_bool_or_number(int, k, v) -def parse_bool_or_number(numtype, k, v, auto=0) -> Union[int,bool]: +def parse_bool_or_number(numtype:Callable, k:str, v, auto=0) -> Union[int,bool]: if isinstance(v, str): v = v.lower() if v in TRUE_OPTIONS: @@ -1445,7 +1445,7 @@ def fixup_compression(options) -> None: if cstr=="all": compressors = compression.PERFORMANCE_ORDER elif cstr=="none": - compressors = [] + compressors = () else: compressors = nodupes(cstr) unknown = tuple(x for x in compressors if x and x not in compression.ALL_COMPRESSORS) diff --git a/xpra/scripts/main.py b/xpra/scripts/main.py index 1e533c7334..c91d9bb2b9 100755 --- a/xpra/scripts/main.py +++ b/xpra/scripts/main.py @@ -18,7 +18,7 @@ import signal import shlex import traceback -from typing import Callable +from typing import Callable, List, Optional, Union, Dict, Any from xpra import __version__ as XPRA_VERSION from xpra.platform.dotxpra import DotXpra @@ -43,6 +43,7 @@ MODE_ALIAS, ) from xpra.scripts.config import ( + XpraConfig, OPTION_TYPES, TRUE_OPTIONS, FALSE_OPTIONS, OFF_OPTIONS, ALL_BOOLEAN_OPTIONS, NON_COMMAND_LINE_OPTIONS, CLIENT_ONLY_OPTIONS, CLIENT_OPTIONS, START_COMMAND_OPTIONS, BIND_OPTIONS, PROXY_START_OVERRIDABLE_OPTIONS, OPTIONS_ADDED_SINCE_V3, OPTIONS_COMPAT_NAMES, @@ -73,14 +74,14 @@ def nox() -> str: # be noticed: import warnings warnings.filterwarnings("error", "could not open display") - return DISPLAY or os.environ.get("WAYLAND_DISPLAY") + return str(DISPLAY or "") or os.environ.get("WAYLAND_DISPLAY", "") def werr(*msg) -> None: for x in msg: noerr(sys.stderr.write, "%s\n" % (x,)) noerr(sys.stderr.flush) -def add_process(*args, **kwargs) -> None: +def add_process(*args, **kwargs): from xpra.child_reaper import getChildReaper return getChildReaper().add_process(*args, **kwargs) @@ -116,29 +117,29 @@ def main(script_file:str, cmdline) -> int: if envbool("XPRA_NOMD5", False): import hashlib try: - hashlib.algorithms_available.remove("md5") # @UndefinedVariable + hashlib.algorithms_available.remove("md5") # type: ignore[attr-defined] #@UndefinedVariable except KeyError: pass else: - def nomd5(*_args): + def nomd5(*_anyargs): raise ValueError("md5 support is disabled") - hashlib.md5 = nomd5 + hashlib.md5 = nomd5 # type: ignore if envbool("XPRA_NOSHA1", False): import hashlib # @Reimport try: - hashlib.algorithms_available.remove("sha1") # @UndefinedVariable + hashlib.algorithms_available.remove("sha1") # type: ignore[attr-defined] #@UndefinedVariable except KeyError: pass else: - def nosha1(*_args): + def nosha1(*_anyargs): raise ValueError("sha1 support is disabled") - hashlib.sha1 = nosha1 + hashlib.sha1 = nosha1 # type: ignore - def debug_exc(msg="run_mode error"): + def debug_exc(msg:str="run_mode error"): get_util_logger().debug(msg, exc_info=True) try: - defaults = make_defaults_struct() + defaults : XpraConfig = make_defaults_struct() fixup_defaults(defaults) options, args = do_parse_cmdline(cmdline, defaults) #set_proc_title is here so we can override the cmdline later @@ -745,7 +746,7 @@ def find_session_by_name(opts, session_name:str) -> str: dotxpra = DotXpra(opts.socket_dir, opts.socket_dirs) socket_paths = dotxpra.socket_paths(check_uid=getuid(), matching_state=DotXpra.LIVE) if not socket_paths: - return None + return "" id_sessions = {} for socket_path in socket_paths: cmd = get_nodock_command()+["id", f"socket://{socket_path}"] @@ -770,7 +771,7 @@ def find_session_by_name(opts, session_name:str) -> str: if name==session_name and uuid: session_uuid_to_path[uuid] = socket_path if not session_uuid_to_path: - return None + return "" if len(session_uuid_to_path)>1: raise InitException(f"more than one session found matching {session_name!r}") socket_path = tuple(session_uuid_to_path.values())[0] @@ -818,7 +819,7 @@ def display_desc_to_display_path(display_desc:dict) -> str: return uri -def pick_vnc_display(error_cb, opts, extra_args) -> dict: +def pick_vnc_display(error_cb, opts, extra_args) -> Dict[str,Any]: if extra_args and len(extra_args)==1: try: display = extra_args[0].lstrip(":") @@ -835,6 +836,7 @@ def pick_vnc_display(error_cb, opts, extra_args) -> dict: "type" : "tcp", } error_cb("cannot find vnc displays yet") + return {} def pick_display(error_cb, opts, extra_args, cmdline=()): @@ -1190,7 +1192,7 @@ def run_send_file(extra_args) -> int: from xpra.gtk_common.gtk_util import choose_files files = choose_files(None, "Select Files to Transfer", multiple=True) if not files: - return + return ExitCode.FAILURE filelog = Logger("file") from xpra.platform.paths import get_xpra_command xpra_cmd = get_xpra_command() @@ -1567,8 +1569,8 @@ def handshake_complete(*_args): opts.mmap_group, opts.socket_permissions, get_username(), getuid, getgid) sockets.update(local_sockets) - listen_cleanup = [] - socket_cleanup = [] + listen_cleanup : List[Callable] = [] + socket_cleanup : List[Callable] = [] def new_connection(socktype, sock, handle=0): from xpra.make_thread import start_thread netlog = get_network_logger() @@ -1611,7 +1613,7 @@ def run_socket_cleanups(): for socktype, sock, sinfo, cleanup_socket in sockets: socket_cleanup.append(cleanup_socket) cleanup = add_listen_socket(socktype, sock, sinfo, None, new_connection) - if cleanup: + if cleanup is not None: listen_cleanup.append(cleanup) #listen mode is special, #don't fall through to connect_to_server! @@ -1635,7 +1637,7 @@ def run_socket_cleanups(): return app -def make_progress_process(title="Xpra") -> Popen: +def make_progress_process(title="Xpra") -> Optional[Popen]: #start the splash subprocess env = os.environ.copy() env["XPRA_LOG_PREFIX"] = "splash: " @@ -1648,11 +1650,12 @@ def make_progress_process(title="Xpra") -> Popen: return None #always close stdin when terminating the splash screen process: saved_terminate = progress_process.terminate - def terminate(): + def terminate(*_args): noerr(progress_process.stdin.close) progress_process.stdin = None saved_terminate() - progress_process.terminate = terminate + #override Popen.terminate() + setattr(progress_process, "terminate", terminate) def progress(pct, text): if progress_process.poll(): return @@ -1823,7 +1826,7 @@ def do_run_client(app) -> int: app.cleanup() -def get_start_new_session_dict(opts, mode, extra_args) -> dict: +def get_start_new_session_dict(opts, mode, extra_args) -> Dict[str,Any]: sns = { "mode" : mode, #ie: "start-desktop" } @@ -1923,19 +1926,19 @@ def run_server(script_file, cmdline, error_cb, options, args, mode:str, defaults from xpra.scripts.server import do_run_server except ImportError: error_cb("Xpra server is not installed") - return do_run_server(script_file, cmdline, error_cb, options, args, mode, display, defaults) + return do_run_server(script_file, cmdline, error_cb, options, args, mode, str(display or ""), defaults) -def start_server_via_proxy(script_file:str, cmdline, error_cb, options, args, mode:str) -> None: +def start_server_via_proxy(script_file:str, cmdline, error_cb, options, args, mode:str) -> Union[int,None]: start_via_proxy = parse_bool("start-via-proxy", options.start_via_proxy) if start_via_proxy is False: - return + return None if not options.daemon: if start_via_proxy is True: error_cb("cannot start-via-proxy without daemonizing") - return + return None if POSIX and getuid()==0: error_cb("cannot start via proxy for root") - return + return None try: from xpra import client #pylint: disable=import-outside-toplevel assert client @@ -1977,11 +1980,12 @@ def start_server_via_proxy(script_file:str, cmdline, error_cb, options, args, mo err = str(e) if start_via_proxy is True: error_cb(f"failed to start-via-proxy: {err}") - return + return None #warn and fall through to regular server start: warn(f"Warning: cannot use the system proxy for {mode!r} subcommand,") warn(f" {err}") warn(" more information may be available in your system log") + return None def run_remote_server(script_file:str, cmdline, error_cb, opts, args, mode:str, defaults) -> int: @@ -2133,11 +2137,11 @@ def handshake_complete(*_args): return r -def find_wayland_display_sockets(uid:int=getuid(), gid:int=getgid()) -> dict: +def find_wayland_display_sockets(uid:int=getuid(), gid:int=getgid()) -> Dict[str,str]: if WIN32 or OSX: return {} displays = {} - def addwaylandsock(d, p): + def addwaylandsock(d:str, p:str): if os.path.isabs(p) and is_socket(p) and os.path.exists(p) and d not in displays: displays[d] = p from xpra.platform.posix.paths import get_runtime_dir @@ -2155,7 +2159,7 @@ def addwaylandsock(d, p): X11_SOCKET_DIR = "/tmp/.X11-unix" -def find_x11_display_sockets(max_display_no:int=None) -> dict: +def find_x11_display_sockets(max_display_no:int=None) -> Dict[str,str]: displays = {} if not os.path.exists(X11_SOCKET_DIR): return displays @@ -2178,7 +2182,7 @@ def find_x11_display_sockets(max_display_no:int=None) -> dict: return displays -def stat_display_socket(socket_path:str, timeout=VERIFY_SOCKET_TIMEOUT) -> dict: +def stat_display_socket(socket_path:str, timeout=VERIFY_SOCKET_TIMEOUT) -> Dict[str,Any]: try: #check that this is a socket sstat = os.stat(socket_path) @@ -2250,7 +2254,7 @@ def dinfo(display): args = args[:-1] -def find_displays(max_display_no=None, uid:int=getuid(), gid:int=getgid()) -> dict: +def find_displays(max_display_no=None, uid:int=getuid(), gid:int=getgid()) -> Dict[str,Any]: if OSX or WIN32: return {"Main" : {}} displays = {} @@ -2372,7 +2376,7 @@ def run_glprobe(opts, show=False) -> int: return 2 return 0 -def do_run_glcheck(opts, show=False) -> dict: +def do_run_glcheck(opts, show=False) -> Dict[str,Any]: #suspend all logging: saved_level = None log = Logger("opengl") @@ -3502,9 +3506,9 @@ def run_clean_displays(options, args) -> int: print("Done") return 0 -def get_displays_info(dotxpra=None, display_names=None, sessions_dir=None) -> dict: +def get_displays_info(dotxpra=None, display_names=None, sessions_dir=None) -> Dict[str,Any]: displays = get_displays(dotxpra, display_names) - displays_info = {} + displays_info : Dict[str,Any] = {} for display, descr in displays.items(): #descr already contains the uid, gid displays_info[display] = descr @@ -3513,7 +3517,7 @@ def get_displays_info(dotxpra=None, display_names=None, sessions_dir=None) -> di sn = sorted_nicely(displays_info.keys()) return dict((k,displays_info[k]) for k in sn) -def get_display_info(display, sessions_dir=None) -> dict: +def get_display_info(display, sessions_dir=None) -> Dict[str,Any]: display_info = {"state" : "LIVE"} if OSX or not POSIX: return display_info @@ -3521,7 +3525,7 @@ def get_display_info(display, sessions_dir=None) -> dict: return {} return get_x11_display_info(display, sessions_dir) -def get_x11_display_info(display, sessions_dir=None) -> dict: +def get_x11_display_info(display, sessions_dir=None) -> Dict[str,Any]: log = Logger("util") log(f"get_x11_display_info({display}, {sessions_dir})") #assume live: @@ -3584,7 +3588,7 @@ def get_x11_display_info(display, sessions_dir=None) -> dict: display_info.update({"state" : "UNKNOWN"}) return display_info -def get_displays(dotxpra=None, display_names=None) -> dict: +def get_displays(dotxpra=None, display_names=None) -> Dict[str,Any]: if OSX or WIN32: return {"Main" : {}} log = get_util_logger() @@ -3618,7 +3622,7 @@ def run_list_sessions(args, options) -> int: attrs.get("session-name", ""))) return 0 -def display_wm_info(args) -> dict: +def display_wm_info(args) -> Dict[str,Any]: assert POSIX and not OSX, "wminfo is not supported on this platform" no_gtk() if len(args)==1: @@ -3654,7 +3658,7 @@ def run_wmname(args) -> int: print(name) return 0 -def exec_wminfo(display) -> dict: +def exec_wminfo(display) -> Dict[str,str]: log = Logger("util") #get the window manager info by executing the "wminfo" subcommand: try: @@ -3678,7 +3682,7 @@ def exec_wminfo(display) -> dict: wminfo[parts[0]] = parts[1] return wminfo -def get_xpra_sessions(dotxpra:DotXpra, ignore_state=(DotXpra.UNKNOWN,), matching_display=None, query:bool=True) -> dict: +def get_xpra_sessions(dotxpra:DotXpra, ignore_state=(DotXpra.UNKNOWN,), matching_display=None, query:bool=True) -> Dict[str,Any]: results = dotxpra.socket_details(matching_display=matching_display) log = get_util_logger() log("get_xpra_sessions%s socket_details=%s", (dotxpra, ignore_state, matching_display), results) diff --git a/xpra/scripts/parsing.py b/xpra/scripts/parsing.py index fbe8ee5ef0..04d8ce1fe3 100755 --- a/xpra/scripts/parsing.py +++ b/xpra/scripts/parsing.py @@ -13,13 +13,14 @@ import os.path import optparse from urllib import parse -from typing import Any, Dict, Tuple +from typing import Any, Dict, Tuple, Optional from xpra.version_util import full_version_str from xpra.util import envbool, csv, parse_simple_dict from xpra.net.common import DEFAULT_PORT, DEFAULT_PORTS from xpra.os_util import WIN32, OSX, POSIX, get_user_uuid from xpra.scripts.config import ( + XpraConfig, OPTION_TYPES, TRUE_OPTIONS, InitException, InitInfo, InitExit, fixup_debug_option, fixup_options, @@ -28,7 +29,7 @@ ) -MODE_ALIAS = { +MODE_ALIAS : Dict[str,str] = { "start" : "seamless", "start-seamless" : "seamless", "start-desktop" : "desktop", @@ -98,7 +99,7 @@ def exit(self, status=0, msg=None): raise InitExit(status, msg) -def fixup_defaults(defaults): +def fixup_defaults(defaults:XpraConfig): for k in ("debug", "encoding", "audio-source", "microphone-codec", "speaker-codec"): fn = k.replace("-", "_") v = getattr(defaults, fn) @@ -112,14 +113,14 @@ def fixup_defaults(defaults): else: v.remove("help") -def do_replace_option(cmdline, oldoption, newoption): +def do_replace_option(cmdline, oldoption:str, newoption:str): for i, x in enumerate(cmdline): if x==oldoption: cmdline[i] = newoption elif newoption.find("=")<0 and x.startswith(f"{oldoption}="): cmdline[i] = f"{newoption}=" + x.split("=", 1)[1] -def do_legacy_bool_parse(cmdline, optionname, newoptionname=None): +def do_legacy_bool_parse(cmdline, optionname:str, newoptionname:Optional[str]=None): #find --no-XYZ or --XYZ #and replace it with --XYZ=yes|no if newoptionname is None: @@ -144,8 +145,8 @@ def ignore_options(args, options): args.remove(r) -def parse_env(env) -> dict: - d = {} +def parse_env(env) -> Dict[str, str]: + d : Dict[str, str] = {} for ev in env: try: if ev.startswith("#"): @@ -197,7 +198,7 @@ def _sep_pos(display_name): return min(scpos, slpos) -def auto_proxy(scheme, host:str) -> dict: +def auto_proxy(scheme, host:str) -> Dict[str,Any]: try: from xpra.net.libproxy import ProxyFactory except ImportError as e: @@ -222,7 +223,7 @@ def auto_proxy(scheme, host:str) -> dict: options["proxy-password"] = url.password return options -def parse_remote_display(s:str) -> dict: +def parse_remote_display(s:str) -> Dict[str,Any]: if not s: return {} qpos = s.find("?") @@ -281,7 +282,7 @@ def parse_remote_display(s:str) -> dict: desc[k] = v return desc -def parse_username_and_password(s:str) -> dict: +def parse_username_and_password(s:str) -> Dict[str,str]: ppos = s.find(":") if ppos>=0: password = s[ppos+1:] @@ -578,7 +579,7 @@ def add_query(): error_cb(f"unknown format for display name: {display_name!r}") -def get_ssl_options(desc, opts, cmdline) -> dict: +def get_ssl_options(desc, opts, cmdline) -> Dict[str,Any]: port = desc["port"] ssl_host = opts.ssl_server_hostname or desc["host"] from xpra.net.socket_util import get_ssl_attributes, load_ssl_options @@ -622,7 +623,7 @@ def parse_ssh_option(ssh_setting:str) -> list: ssh_cmd = shlex.split(DEFAULT_SSH_COMMAND) return ssh_cmd -def get_ssh_display_attributes(args, ssh_option="auto") -> dict: +def get_ssh_display_attributes(args, ssh_option="auto") -> Dict[str,Any]: #ie: ssh=["/usr/bin/ssh", "-v"] ssh = parse_ssh_option(ssh_option) ssh_cmd = ssh[0].lower() @@ -1804,7 +1805,7 @@ def pws_fail(): options.tcp_encryption = f"AES-{DEFAULT_MODE}" return options, args -def validated_encodings(encodings) -> tuple: +def validated_encodings(encodings) -> Tuple[str]: try: from xpra.codecs.codec_constants import preforder except ImportError: diff --git a/xpra/scripts/server.py b/xpra/scripts/server.py index d7427496cf..f3614f3d52 100644 --- a/xpra/scripts/server.py +++ b/xpra/scripts/server.py @@ -16,6 +16,7 @@ import os.path import datetime from subprocess import Popen #pylint: disable=import-outside-toplevel +from typing import Dict, Any from xpra import __version__ from xpra.scripts.main import ( @@ -162,7 +163,7 @@ def configure_imsettings_env(input_method) -> str: warn(" if it is correct, you may want to file a bug to get it recognized") return im -def imsettings_env(disabled, gtk_im_module, qt_im_module, clutter_im_module, imsettings_module, xmodifiers) -> dict: +def imsettings_env(disabled, gtk_im_module, qt_im_module, clutter_im_module, imsettings_module, xmodifiers) -> Dict[str,str]: #for more information, see imsettings: #https://code.google.com/p/imsettings/source/browse/trunk/README if disabled is True: @@ -533,7 +534,7 @@ def get_options_file_contents(opts, mode:str="seamless") -> str: diff_contents.append("") return "\n".join(diff_contents) -def load_options() -> dict: +def load_options() -> Dict[str,Any]: config_file = session_file_path("config") return read_config(config_file) diff --git a/xpra/server/gtk_server_base.py b/xpra/server/gtk_server_base.py index f439bdf2b5..bb1554e487 100644 --- a/xpra/server/gtk_server_base.py +++ b/xpra/server/gtk_server_base.py @@ -10,6 +10,7 @@ import sys from time import monotonic +from typing import Dict, Any import gi gi.require_version('Gdk', '3.0') # @UndefinedVariable @@ -138,7 +139,7 @@ def do_run(self) -> None: log("do_run() end of gtk.main()") - def make_hello(self, source) -> dict: + def make_hello(self, source) -> Dict[str,Any]: capabilities = super().make_hello(source) if "display" in source.wants: display = Gdk.Display.get_default() @@ -153,7 +154,7 @@ def make_hello(self, source) -> dict: capabilities.update(flatten_dict(get_gtk_version_info())) return capabilities - def get_ui_info(self, proto, *args) -> dict: + def get_ui_info(self, proto, *args) -> Dict[str,Any]: info = super().get_ui_info(proto, *args) display = Gdk.Display.get_default() if display: @@ -196,7 +197,7 @@ def send_initial_cursors(self, ss, _sharing=False) -> None: cursorlog("send_initial_cursors() cursor_sizes=%s", self.cursor_sizes) ss.send_cursor() - def get_ui_cursor_info(self) -> dict: + def get_ui_cursor_info(self) -> Dict[str,Any]: #(from UI thread) #now cursor size info: display = Gdk.Display.get_default() @@ -213,7 +214,7 @@ def get_ui_cursor_info(self) -> dict: cinfo[f"{prop}_size"] = size return cinfo - def do_get_info(self, proto, *args) -> dict: + def do_get_info(self, proto, *args) -> Dict[str,Any]: start = monotonic() info = super().do_get_info(proto, *args) vi = dict_version_trim(get_gtk_version_info()) diff --git a/xpra/server/keyboard_config_base.py b/xpra/server/keyboard_config_base.py index 53f1454a56..221cc5ae37 100644 --- a/xpra/server/keyboard_config_base.py +++ b/xpra/server/keyboard_config_base.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2018 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. +from typing import Dict, Any + class KeyboardConfigBase: """ Base class representing the keyboard configuration for a server. @@ -18,7 +20,7 @@ def __init__(self): def __repr__(self): return "KeyboardConfigBase" - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return { "enabled" : self.enabled, "owner" : self.owner or "", diff --git a/xpra/server/menu_provider.py b/xpra/server/menu_provider.py index 8de9b742c9..5f56c78101 100644 --- a/xpra/server/menu_provider.py +++ b/xpra/server/menu_provider.py @@ -1,11 +1,12 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2022 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import os.path from threading import Lock +from typing import Dict, Any, Optional from gi.repository import GLib # @UnresolvedImport @@ -153,7 +154,7 @@ def load(): self.clear_cache() start_thread(load, "load-menu-data", True) - def get_menu_data(self, force_reload=False, remove_icons=False, wait=True): + def get_menu_data(self, force_reload=False, remove_icons=False, wait=True) -> Optional[Dict[str,Any]]: log("get_menu_data%s", (force_reload, remove_icons, wait)) if not EXPORT_XDG_MENU_DATA: return None @@ -240,5 +241,5 @@ def get_desktop_menu_icon(self, sessionname): return de.get("IconType"), de.get("IconData") - def get_info(self, _proto) -> dict: + def get_info(self, _proto) -> Dict[str,Any]: return self.get_menu_data(remove_icons=True) diff --git a/xpra/server/mixins/audio_server.py b/xpra/server/mixins/audio_server.py index d632a2b41c..5c0ef6bcf3 100644 --- a/xpra/server/mixins/audio_server.py +++ b/xpra/server/mixins/audio_server.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2022 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Copyright (C) 2008 Nathaniel Smith # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -10,6 +10,7 @@ from time import monotonic from subprocess import Popen, PIPE from threading import Event +from typing import Dict, Any, Callable from xpra.os_util import pollwait, osexpand, OSX, POSIX from xpra.util import typedict, envbool, csv, engs @@ -84,7 +85,7 @@ def cleanup(self): self.cleanup_pulseaudio() - def get_info(self, _proto) -> dict: + def get_info(self, _proto) -> Dict[str,Any]: self.audio_init_done.wait(5) info = {} if self.pulseaudio is not False: @@ -94,7 +95,7 @@ def get_info(self, _proto) -> dict: return {} - def get_server_features(self, source) -> dict: + def get_server_features(self, source) -> Dict[str,Any]: d = { "av-sync" : { "" : self.av_sync, @@ -105,7 +106,7 @@ def get_server_features(self, source) -> dict: return d - def get_http_scripts(self) -> dict: + def get_http_scripts(self) -> Dict[str,Callable]: return {} @@ -363,7 +364,7 @@ def log_audio_properties(self): audiolog("init_audio_options audio properties=%s", self.audio_properties) - def get_pulseaudio_info(self) -> dict: + def get_pulseaudio_info(self) -> Dict[str,Any]: info = { "command" : self.pulseaudio_command, "configure-commands" : self.pulseaudio_configure_commands, diff --git a/xpra/server/mixins/child_command_server.py b/xpra/server/mixins/child_command_server.py index d0cd258280..31fb4b6057 100644 --- a/xpra/server/mixins/child_command_server.py +++ b/xpra/server/mixins/child_command_server.py @@ -54,10 +54,10 @@ def __init__(self): self.children_count : int = 0 self.start_after_connect_done : bool = False self.start_new_commands : bool = False - self.source_env = {} - self.start_env = {} - self.exec_cwd = None - self.exec_wrapper = None + self.source_env : Dict[str, str] = {} + self.start_env : Dict[str, str] = {} + self.exec_cwd : str = os.getcwd() + self.exec_wrapper : List[str] = [] self.terminate_children : bool = False self.children_started : List[ProcInfo] = [] self.child_reaper = None @@ -100,7 +100,7 @@ def init(self, opts) -> None: if opts.exec_wrapper: self.exec_wrapper = shlex.split(opts.exec_wrapper) self.child_reaper = getChildReaper() - self.source_env : Dict[str, str] = source_env(opts.source_start) + self.source_env = source_env(opts.source_start) self.start_env = parse_env(opts.start_env) if self.start_new_commands: #may already have been initialized by servercore: @@ -180,7 +180,7 @@ def send_updated_menu(self, xdg_menu) -> None: def get_info(self, _proto) -> Dict[str,Any]: - info : Dict[str,Any] = { + info = { "start" : self.start_commands, "start-late" : self.start_late_commands, "start-child" : self.start_child_commands, @@ -203,7 +203,8 @@ def get_info(self, _proto) -> Dict[str,Any]: }) for i,procinfo in enumerate(self.children_started): info[i] = procinfo.get_info() - return {"commands": info} + cinfo : Dict[str,Any] = {"commands": info} + return cinfo def last_client_exited(self) -> None: diff --git a/xpra/server/mixins/clipboard_server.py b/xpra/server/mixins/clipboard_server.py index cad2435748..2005a9a602 100644 --- a/xpra/server/mixins/clipboard_server.py +++ b/xpra/server/mixins/clipboard_server.py @@ -1,11 +1,12 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2022 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Copyright (C) 2008 Nathaniel Smith # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import os.path +from typing import Dict, Any from xpra.platform.features import ( CLIPBOARDS, CLIPBOARD_PREFERRED_TARGETS, @@ -30,7 +31,7 @@ def __init__(self): self.clipboard_filter_file = None self._clipboard_helper = None - def init(self, opts): + def init(self, opts) -> None: self.clipboard = (opts.clipboard or "").lower() not in FALSE_OPTIONS self.clipboard_direction = opts.clipboard_direction self.clipboard_filter_file = opts.clipboard_filter_file @@ -38,25 +39,25 @@ def init(self, opts): def setup(self): self.init_clipboard() - def cleanup(self): + def cleanup(self) -> None: ch = self._clipboard_helper if ch: self._clipboard_helper = None ch.cleanup() - def cleanup_protocol(self, protocol): + def cleanup_protocol(self, protocol) -> None: ch = self._clipboard_helper if ch and self._clipboard_client and self._clipboard_client.protocol==protocol: self._clipboard_client = None ch.client_reset() - def parse_hello(self, ss, _caps, send_ui): + def parse_hello(self, ss, _caps, send_ui) -> None: if send_ui and self.clipboard: self.parse_hello_ui_clipboard(ss) - def get_info(self, _proto) -> dict: + def get_info(self, _proto) -> Dict[str,Any]: if self._clipboard_helper is None: return {} ci = self._clipboard_helper.get_info() @@ -66,7 +67,7 @@ def get_info(self, _proto) -> dict: return {"clipboard" : ci} - def get_server_features(self, server_source=None) -> dict: + def get_server_features(self, server_source=None) -> Dict[str,Any]: clipboard = self._clipboard_helper is not None log("clipboard_helper=%s, clipboard_client=%s, source=%s, clipboard=%s", self._clipboard_helper, self._clipboard_client, server_source, clipboard) @@ -91,7 +92,7 @@ def get_server_features(self, server_source=None) -> dict: "clipboard-direction" : self.clipboard_direction, } - def init_clipboard(self): + def init_clipboard(self) -> None: log("init_clipboard() enabled=%s, filter file=%s", self.clipboard, self.clipboard_filter_file) ### Clipboard handling: self._clipboard_helper = None @@ -139,7 +140,7 @@ def init_clipboard(self): log.error("Error: failed to setup clipboard helper", exc_info=True) self.clipboard = False - def parse_hello_ui_clipboard(self, ss): + def parse_hello_ui_clipboard(self, ss) -> None: #take the clipboard if no-one else has it yet: if not getattr(ss, "clipboard_enabled", False): log("client does not support clipboard") @@ -153,7 +154,7 @@ def parse_hello_ui_clipboard(self, ss): return self.set_clipboard_source(ss) - def set_clipboard_source(self, ss): + def set_clipboard_source(self, ss) -> None: if not getattr(ss, "clipboard_enabled", False): #don't use this client as clipboard source! #(its clipboard is disabled) @@ -179,17 +180,17 @@ def set_clipboard_source(self, ss): ch.enable_selections(None) - def last_client_exited(self): + def last_client_exited(self) -> None: ch = self._clipboard_helper if ch: ch.client_reset() - def set_session_driver(self, source): + def set_session_driver(self, source) -> None: self.set_clipboard_source(source) - def _process_clipboard_packet(self, proto, packet): + def _process_clipboard_packet(self, proto, packet) -> None: assert self.clipboard if self.readonly: return @@ -210,7 +211,7 @@ def _process_clipboard_packet(self, proto, packet): assert ch, "received a clipboard packet but clipboard sharing is disabled" self.idle_add(ch.process_clipboard_packet, packet) - def _process_clipboard_enabled_status(self, proto, packet): + def _process_clipboard_enabled_status(self, proto, packet) -> None: assert self.clipboard if self.readonly: return @@ -219,7 +220,7 @@ def _process_clipboard_enabled_status(self, proto, packet): if ss: self.set_clipboard_enabled_status(ss, clipboard_enabled) - def set_clipboard_enabled_status(self, ss, clipboard_enabled): + def set_clipboard_enabled_status(self, ss, clipboard_enabled:bool) -> None: ch = self._clipboard_helper if not ch: log.warn("Warning: client try to toggle clipboard-enabled status,") @@ -239,18 +240,18 @@ def set_clipboard_enabled_status(self, ss, clipboard_enabled): if not clipboard_enabled: ch.enable_selections(None) - def clipboard_progress(self, local_requests, _remote_requests): + def clipboard_progress(self, local_requests, _remote_requests) -> None: assert self.clipboard if self._clipboard_client: self._clipboard_client.send_clipboard_progress(local_requests) - def send_clipboard_packet(self, *parts): + def send_clipboard_packet(self, *parts) -> None: assert self.clipboard if self._clipboard_client: self._clipboard_client.send_clipboard(parts) - def init_packet_handlers(self): + def init_packet_handlers(self) -> None: if self.clipboard: self.add_packet_handler("set-clipboard-enabled", self._process_clipboard_enabled_status) for x in ( diff --git a/xpra/server/mixins/dbusrpc_server.py b/xpra/server/mixins/dbusrpc_server.py index 9df82ae782..b56b985e22 100644 --- a/xpra/server/mixins/dbusrpc_server.py +++ b/xpra/server/mixins/dbusrpc_server.py @@ -1,11 +1,12 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2020 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Copyright (C) 2008 Nathaniel Smith # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import os +from typing import Dict, Any from xpra.server.mixins.stub_server_mixin import StubServerMixin from xpra.log import Logger @@ -24,25 +25,25 @@ def __init__(self): self.supports_dbus_proxy = False self.dbus_helper = None - def init(self, opts): + def init(self, opts) -> None: self.supports_dbus_proxy = opts.dbus_proxy - def setup(self): + def setup(self) -> None: self.init_dbus_helper() - def get_server_features(self, _source=None): + def get_server_features(self, _source=None) -> Dict[str,Any]: return { "dbus_proxy" : self.supports_dbus_proxy, "rpc-types" : tuple(self.rpc_handlers.keys()), } - def get_info(self, _proto) -> dict: + def get_info(self, _proto) -> Dict[str,Any]: return {} - def init_dbus_helper(self): + def init_dbus_helper(self) -> None: if not self.supports_dbus_proxy: return try: @@ -62,7 +63,7 @@ def make_dbus_server(self): from xpra.server.dbus.dbus_server import DBUS_Server # pylint: disable=import-outside-toplevel return DBUS_Server(self, os.environ.get("DISPLAY", "").lstrip(":")) - def _handle_dbus_rpc(self, ss, rpcid, _, bus_name, path, interface, function, args, *_extra): + def _handle_dbus_rpc(self, ss, rpcid, _, bus_name, path, interface, function, args, *_extra) -> None: assert self.supports_dbus_proxy, "server does not support dbus proxy calls" def native(args): return [self.dbus_helper.dbus_to_native(x) for x in (args or [])] @@ -75,7 +76,7 @@ def err_back(*args): self.dbus_helper.call_function(bus_name, path, interface, function, args, ok_back, err_back) - def _process_rpc(self, proto, packet): + def _process_rpc(self, proto, packet) -> None: if self.readonly: return ss = self.get_server_source(proto) @@ -94,6 +95,6 @@ def _process_rpc(self, proto, packet): ss.rpc_reply(rpc_type, rpcid, False, str(e)) - def init_packet_handlers(self): + def init_packet_handlers(self) -> None: if self.supports_dbus_proxy: self.add_packet_handler("rpc", self._process_rpc) diff --git a/xpra/server/mixins/display_manager.py b/xpra/server/mixins/display_manager.py index fb3687b983..c7d5156270 100644 --- a/xpra/server/mixins/display_manager.py +++ b/xpra/server/mixins/display_manager.py @@ -4,6 +4,8 @@ # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. +from typing import Dict, Any + from xpra.util import engs, log_screen_sizes, typedict from xpra.os_util import bytestostr, is_Wayland from xpra.version_util import parse_version, dict_version_trim @@ -133,7 +135,7 @@ def query_opengl(self): return props - def get_caps(self, source) -> dict: + def get_caps(self, source) -> Dict[str,Any]: caps = { "bell" : self.bell, "cursors" : self.cursors, @@ -145,7 +147,7 @@ def get_caps(self, source) -> dict: caps["opengl"] = dict_version_trim(self.opengl_props) return caps - def get_info(self, _proto) -> dict: + def get_info(self, _proto) -> Dict[str,Any]: i = { "randr" : self.randr, "bell" : self.bell, @@ -174,13 +176,13 @@ def get_info(self, _proto) -> dict: } - def _process_set_cursors(self, proto, packet): + def _process_set_cursors(self, proto, packet) -> None: assert self.cursors, "cannot toggle send_cursors: the feature is disabled" ss = self.get_server_source(proto) if ss: ss.send_cursors = bool(packet[1]) - def _process_set_bell(self, proto, packet): + def _process_set_bell(self, proto, packet) -> None: assert self.bell, "cannot toggle send_bell: the feature is disabled" ss = self.get_server_source(proto) if ss: @@ -189,11 +191,11 @@ def _process_set_bell(self, proto, packet): ###################################################################### # display / screen / root window: - def set_screen_geometry_attributes(self, w, h): + def set_screen_geometry_attributes(self, w:int, h:int): #by default, use the screen as desktop area: self.set_desktop_geometry_attributes(w, h) - def set_desktop_geometry_attributes(self, w, h): + def set_desktop_geometry_attributes(self, w:int, h:int): self.calculate_desktops() self.calculate_workarea(w, h) self.set_desktop_geometry(w, h) diff --git a/xpra/server/mixins/encoding_server.py b/xpra/server/mixins/encoding_server.py index fd60158049..c8bf9a8ef5 100644 --- a/xpra/server/mixins/encoding_server.py +++ b/xpra/server/mixins/encoding_server.py @@ -5,6 +5,8 @@ # later version. See the file COPYING for details. #pylint: disable-msg=E1101 +from typing import Dict, Any + from xpra.scripts.config import parse_bool_or_int, csvstrl from xpra.util import envint from xpra.os_util import bytestostr, OSX @@ -103,7 +105,7 @@ def get_server_features(self, _source=None): "auto-video-encoding" : True, #from v4.0, clients assume this is available } - def get_info(self, _proto) -> dict: + def get_info(self, _proto) -> Dict[str,Any]: info = { "encodings" : self.get_encoding_info(), "video" : getVideoHelper().get_info(), @@ -113,7 +115,7 @@ def get_info(self, _proto) -> dict: info.setdefault("encoding", {}).setdefault(k, {})["version"] = vtrim(v) return info - def get_encoding_info(self) -> dict: + def get_encoding_info(self) -> Dict[str,Any]: return { "" : self.encodings, "core" : self.core_encodings, diff --git a/xpra/server/mixins/logging_server.py b/xpra/server/mixins/logging_server.py index e80a211ec0..4c309b8700 100644 --- a/xpra/server/mixins/logging_server.py +++ b/xpra/server/mixins/logging_server.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2021 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. #pylint: disable-msg=E1101 @@ -10,6 +10,7 @@ import traceback from time import monotonic from threading import Lock +from typing import Dict, Any from xpra.os_util import bytestostr from xpra.util import repr_ellipsized, net_utf8 @@ -26,26 +27,26 @@ class LoggingServer(StubServerMixin): """ def __init__(self): - self.remote_logging_send = False - self.remote_logging_receive = False - self.logging_lock = Lock() - self.log_both = False - self.in_remote_logging = False + self.remote_logging_send : bool = False + self.remote_logging_receive : bool = False + self.logging_lock : Lock = Lock() + self.log_both : bool = False + self.in_remote_logging : bool = False self.local_logging = None self.logging_clients = {} - def init(self, opts): + def init(self, opts) -> None: self.log_both = (opts.remote_logging or "").lower()=="both" if opts.remote_logging.lower() not in FALSE_OPTIONS: self.remote_logging_send = opts.remote_logging.lower() in ("allow", "send", "both") #"yes" is here for backwards compatibility: self.remote_logging_receive = opts.remote_logging.lower() in ["allow", "receive", "both"]+list(TRUE_OPTIONS) - def cleanup(self): + def cleanup(self) -> None: self.stop_capturing_logging() - def get_server_features(self, _source=None) -> dict: + def get_server_features(self, _source=None) -> Dict[str,Any]: return { "remote-logging" : { "receive" : self.remote_logging_receive, @@ -57,17 +58,17 @@ def get_server_features(self, _source=None) -> dict: } - def cleanup_protocol(self, protocol): + def cleanup_protocol(self, protocol) -> None: if protocol in self.logging_clients: del self.logging_clients[protocol] - def remove_logging_client(self, protocol): + def remove_logging_client(self, protocol) -> None: if self.logging_clients.pop(protocol, None) is None: log.warn("Warning: logging was not enabled for '%r'", protocol) if not self.logging_clients: self.stop_capturing_logging() - def add_logging_client(self, protocol): + def add_logging_client(self, protocol) -> None: n = len(self.logging_clients) if protocol in self.logging_clients: log.warn("Warning: logging already enabled for client %s", protocol) @@ -78,18 +79,18 @@ def add_logging_client(self, protocol): self.start_capturing_logging() - def start_capturing_logging(self): + def start_capturing_logging(self) -> None: if not self.local_logging: self.local_logging = set_global_logging_handler(self.remote_logging_handler) - def stop_capturing_logging(self): + def stop_capturing_logging(self) -> None: ll = self.local_logging if ll: self.local_logging = None set_global_logging_handler(ll) - def remote_logging_handler(self, log, level, msg, *args, **kwargs): + def remote_logging_handler(self, log, level, msg, *args, **kwargs) -> None: #prevent loops (if our send call ends up firing another logging call): if self.in_remote_logging: return @@ -164,7 +165,7 @@ def local_err(message, e=None): self.in_remote_logging = False - def _process_logging_control(self, proto, packet): + def _process_logging_control(self, proto, packet) -> None: action = bytestostr(packet[1]) if action=="start": self.add_logging_client(proto) @@ -173,7 +174,7 @@ def _process_logging_control(self, proto, packet): else: log.warn("Warning: unknown logging-control action '%r'", action) - def _process_logging(self, proto, packet): + def _process_logging(self, proto, packet) -> None: assert self.remote_logging_receive ss = self.get_server_source(proto) if ss is None: @@ -199,11 +200,11 @@ def _process_logging(self, proto, packet): log.error(" %s", repr_ellipsized(msg)) log.estr(e) - def do_log(self, level, line): + def do_log(self, level, line) -> None: with self.logging_lock: log.log(level, line) - def init_packet_handlers(self): + def init_packet_handlers(self) -> None: if self.remote_logging_receive: self.add_packet_handler("logging", self._process_logging, False) if self.remote_logging_send: diff --git a/xpra/server/mixins/mmap_server.py b/xpra/server/mixins/mmap_server.py index e2597b8014..d363a3f5c2 100644 --- a/xpra/server/mixins/mmap_server.py +++ b/xpra/server/mixins/mmap_server.py @@ -1,10 +1,11 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2020 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import os.path +from typing import Dict, Any from xpra.scripts.config import parse_bool from xpra.server.mixins.stub_server_mixin import StubServerMixin @@ -28,7 +29,7 @@ def init(self, opts): self.supports_mmap = bool(parse_bool("mmap", opts.mmap.lower())) - def get_info(self, _proto=None) -> dict: + def get_info(self, _proto=None) -> Dict[str,Any]: return { "mmap" : { "supported" : self.supports_mmap, diff --git a/xpra/server/mixins/networkstate_server.py b/xpra/server/mixins/networkstate_server.py index f022a5244c..a07c89f50f 100644 --- a/xpra/server/mixins/networkstate_server.py +++ b/xpra/server/mixins/networkstate_server.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2020 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. #pylint: disable-msg=E1101 import os from time import sleep +from typing import Dict, Any from xpra.server.mixins.stub_server_mixin import StubServerMixin from xpra.scripts.config import parse_with_unit @@ -41,21 +42,21 @@ def __init__(self): self.cpu_info = None self.print_memleaks = None - def init(self, opts): + def init(self, opts) -> None: self.pings = opts.pings self.bandwidth_limit = parse_with_unit("bandwidth-limit", opts.bandwidth_limit) bandwidthlog("bandwidth-limit(%s)=%s", opts.bandwidth_limit, self.bandwidth_limit) self.init_cpuinfo() - def setup(self): + def setup(self) -> None: self.init_leak_detection() if self.pings>0: self.ping_timer = self.timeout_add(1000*self.pings, self.send_ping) - def threaded_setup(self): + def threaded_setup(self) -> None: self.init_memcheck() - def cleanup(self): + def cleanup(self) -> None: pt = self.ping_timer if pt: self.ping_timer = None @@ -64,7 +65,7 @@ def cleanup(self): if pm: pm() - def get_info(self, _source=None) -> dict: + def get_info(self, _source=None) -> Dict[str,Any]: info = { "pings" : self.pings, "bandwidth-limit" : self.bandwidth_limit or 0, @@ -77,7 +78,7 @@ def get_info(self, _source=None) -> dict: info["cpuinfo"] = dict((k,v) for k,v in self.cpu_info.items() if k!="python_version") return info - def get_server_features(self, _source) -> dict: + def get_server_features(self, _source) -> Dict[str,Any]: return { "connection-data" : True, #added in v2.3 "network" : { @@ -87,7 +88,7 @@ def get_server_features(self, _source) -> dict: } - def init_leak_detection(self): + def init_leak_detection(self) -> None: if DETECT_MEMLEAKS: self.print_memleaks = detect_leaks() if bool(self.print_memleaks): @@ -107,7 +108,7 @@ def print_fds(): return True self.timeout_add(10, print_fds) - def init_memcheck(self): + def init_memcheck(self) -> None: #verify we have enough memory: if POSIX and self.mem_bytes==0: try: @@ -121,7 +122,7 @@ def init_memcheck(self): except Exception: pass - def init_cpuinfo(self): + def init_cpuinfo(self) -> None: if not CPUINFO: return #this crashes if not run from the UI thread! @@ -139,12 +140,12 @@ def init_cpuinfo(self): log.info("%ix %s", count, brand) - def _process_connection_data(self, proto, packet): + def _process_connection_data(self, proto, packet) -> None: ss = self.get_server_source(proto) if ss: ss.update_connection_data(packet[1]) - def _process_bandwidth_limit(self, proto, packet): + def _process_bandwidth_limit(self, proto, packet) -> None: log("_process_bandwidth_limit(%s, %s)", proto, packet) ss = self.get_server_source(proto) if not ss: @@ -179,12 +180,12 @@ def send_ping(self) -> bool: ss.ping() return True - def _process_ping_echo(self, proto, packet): + def _process_ping_echo(self, proto, packet) -> None: ss = self.get_server_source(proto) if ss: ss.process_ping_echo(packet) - def _process_ping(self, proto, packet): + def _process_ping(self, proto, packet) -> None: time_to_echo = packet[1] sid = "" if len(packet)>=4: @@ -194,7 +195,7 @@ def _process_ping(self, proto, packet): ss.process_ping(time_to_echo, sid) - def init_packet_handlers(self): + def init_packet_handlers(self) -> None: self.add_packet_handlers({ "ping": self._process_ping, "ping_echo": self._process_ping_echo, diff --git a/xpra/server/mixins/notification_forwarder.py b/xpra/server/mixins/notification_forwarder.py index ed48a5b6e8..d5b5efba25 100644 --- a/xpra/server/mixins/notification_forwarder.py +++ b/xpra/server/mixins/notification_forwarder.py @@ -1,11 +1,12 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2020 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. #pylint: disable-msg=E1101 import os.path +from typing import Any, Dict from xpra.os_util import OSX, POSIX from xpra.util import ellipsizer @@ -25,24 +26,24 @@ def __init__(self): self.notifications_forwarder = None self.notifications = False - def init(self, opts): + def init(self, opts) -> None: self.notifications = opts.notifications - def setup(self): + def setup(self) -> None: self.init_notification_forwarder() - def cleanup(self): + def cleanup(self) -> None: nf = self.notifications_forwarder if nf: self.notifications_forwarder = None start_thread(nf.release, "notifier-release", daemon=True) - def get_info(self, _source=None) -> dict: + def get_info(self, _source=None)-> Dict[str,Any]: if not self.notifications_forwarder: return {} return {"notifications" : self.notifications_forwarder.get_info()} - def get_server_features(self, _source=None) -> dict: + def get_server_features(self, _source=None)-> Dict[str,Any]: return { "notifications" : { "close" : self.notifications, @@ -52,7 +53,7 @@ def get_server_features(self, _source=None) -> dict: "notifications.actions" : self.notifications, #added in v2.3 } - def parse_hello(self, ss, _caps, send_ui): + def parse_hello(self, ss, _caps, send_ui) -> None: log("parse_hello(%s, {...}, %s) notifications_forwarder=%s", ss, send_ui, self.notifications_forwarder) if send_ui and self.notifications_forwarder: client_notification_actions = dict( @@ -63,7 +64,7 @@ def parse_hello(self, ss, _caps, send_ui): self.notifications_forwarder.support_actions = any(v for v in client_notification_actions.values()) - def init_notification_forwarder(self): + def init_notification_forwarder(self) -> None: log("init_notification_forwarder() enabled=%s", self.notifications) if self.notifications and POSIX and not OSX: try: @@ -76,7 +77,7 @@ def init_notification_forwarder(self): log("init_notification_forwarder()", exc_info=True) self.notify_setup_error(e) - def notify_setup_error(self, exception): + def notify_setup_error(self, exception) -> None: log.warn("Warning: cannot forward notifications,") if str(exception).endswith("is already claimed on the session bus"): log.warn(" the interface is already claimed") @@ -88,7 +89,7 @@ def notify_setup_error(self, exception): log.warn(" use the 'notifications=no' option") - def notify_new_user(self, ss): + def notify_new_user(self, ss) -> None: #tell other users: log("notify_new_user(%s) sources=%s", ss, self._server_sources) if not self._server_sources: @@ -111,7 +112,8 @@ def notify_new_user(self, ss): log.estr(e) - def notify_callback(self, dbus_id, nid, app_name, replaces_nid, app_icon, summary, body, actions, hints, expire_timeout): + def notify_callback(self, dbus_id, nid, app_name, replaces_nid, app_icon, + summary, body, actions, hints, expire_timeout) -> None: assert self.notifications_forwarder and self.notifications #make sure that we run in the main thread: self.idle_add(self.do_notify_callback, dbus_id, nid, @@ -122,7 +124,7 @@ def notify_callback(self, dbus_id, nid, app_name, replaces_nid, app_icon, summar def do_notify_callback(self, dbus_id, nid, app_name, replaces_nid, app_icon, summary, body, - actions, hints, expire_timeout): + actions, hints, expire_timeout) -> None: try: icon = self.get_notification_icon(str(app_icon)) if os.path.isabs(str(app_icon)): @@ -138,23 +140,23 @@ def do_notify_callback(self, dbus_id, nid, log.error("Error processing notification:") log.estr(e) - def get_notification_icon(self, _icon_string): + def get_notification_icon(self, _icon_string:str): return [] - def notify_close_callback(self, nid): + def notify_close_callback(self, nid:int) -> None: assert self.notifications_forwarder log("notify_close_callback(%s)", nid) for ss in self._server_sources.values(): ss.notify_close(int(nid)) - def _process_set_notify(self, proto, packet): + def _process_set_notify(self, proto, packet) -> None: assert self.notifications, "cannot toggle notifications: the feature is disabled" ss = self.get_server_source(proto) if ss: ss.send_notifications = bool(packet[1]) - def _process_notification_close(self, proto, packet): + def _process_notification_close(self, proto, packet) -> None: assert self.notifications nid, reason, text = packet[1:4] ss = self.get_server_source(proto) @@ -174,7 +176,7 @@ def _process_notification_close(self, proto, packet): assert int(reason)>=0 self.notifications_forwarder.NotificationClosed(nid, reason) - def _process_notification_action(self, proto, packet): + def _process_notification_action(self, proto, packet) -> None: assert self.notifications nid, action_key = packet[1:3] ss = self.get_server_source(proto) @@ -195,7 +197,7 @@ def _process_notification_action(self, proto, packet): client_callback(nid, action_key) - def init_packet_handlers(self): + def init_packet_handlers(self) -> None: if self.notifications: self.add_packet_handlers({ "notification-close" : self._process_notification_close, diff --git a/xpra/server/mixins/shell_server.py b/xpra/server/mixins/shell_server.py index 738c01dfca..560936d5b6 100644 --- a/xpra/server/mixins/shell_server.py +++ b/xpra/server/mixins/shell_server.py @@ -1,10 +1,12 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2020 Antoine Martin +# Copyright (C) 2020-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. #pylint: disable-msg=E1101 +from typing import Dict, Any + from xpra.server.mixins.stub_server_mixin import StubServerMixin @@ -13,12 +15,12 @@ class ShellServer(StubServerMixin): Mixin for adding shell support """ - def get_info(self, _source=None) -> dict: + def get_info(self, _source=None) -> Dict[str,Any]: return { "shell" : True, } - def get_server_features(self, _source) -> dict: + def get_server_features(self, _source) -> Dict[str,Any]: return { "shell" : True, } diff --git a/xpra/server/mixins/stub_server_mixin.py b/xpra/server/mixins/stub_server_mixin.py index 9cb762f23a..68a7bc333b 100644 --- a/xpra/server/mixins/stub_server_mixin.py +++ b/xpra/server/mixins/stub_server_mixin.py @@ -5,7 +5,7 @@ import os import shlex -from typing import Callable, Any, List +from typing import Callable, Any, List, Dict from xpra.util import typedict from xpra.os_util import WIN32 @@ -67,13 +67,13 @@ def init_sockets(self, _sockets) -> None: Prepare to handle connections from the given sockets. """ - def get_caps(self, _source) -> dict[str,Any]: + def get_caps(self, _source) -> Dict[str,Any]: """ Capabilities provided by this mixin. """ return {} - def get_server_features(self, _source) -> dict[str,Any]: + def get_server_features(self, _source) -> Dict[str,Any]: """ Features provided by this mixin. (the difference with capabilities is that those will only @@ -87,7 +87,7 @@ def set_session_driver(self, _source) -> None: this method will be called. """ - def get_info(self, _proto) -> dict[str,Any]: + def get_info(self, _proto) -> Dict[str,Any]: """ Runtime information on this mixin, includes state and settings. Somewhat overlaps with the capabilities and features, @@ -95,7 +95,7 @@ def get_info(self, _proto) -> dict[str,Any]: """ return {} - def get_ui_info(self, proto, client_uuids=None, *args) -> dict[str,Any]: + def get_ui_info(self, proto, client_uuids=None, *args) -> Dict[str,Any]: """ Runtime information on this mixin, unlike get_info() this method will be called @@ -130,7 +130,7 @@ def cleanup_protocol(self, protocol) -> None: """ - def get_child_env(self) -> dict[str,str]: + def get_child_env(self) -> Dict[str,str]: return os.environ.copy() @@ -143,7 +143,7 @@ def get_full_child_command(self, cmd, use_wrapper : bool=True) -> List[str]: return shlex.split(str(cmd)) - def get_http_scripts(self) -> dict[str,Callable]: + def get_http_scripts(self) -> Dict[str,Callable]: return {} diff --git a/xpra/server/mixins/webcam_server.py b/xpra/server/mixins/webcam_server.py index 7a4d446c94..c9d8de0f41 100644 --- a/xpra/server/mixins/webcam_server.py +++ b/xpra/server/mixins/webcam_server.py @@ -1,11 +1,12 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2020 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. #pylint: disable-msg=E1101 import os.path +from typing import Dict, Any from xpra.os_util import OSX, POSIX, bytestostr from xpra.util import engs @@ -42,7 +43,7 @@ def threaded_setup(self): self.init_webcam() - def get_server_features(self, _source) -> dict: + def get_server_features(self, _source) -> Dict[str,Any]: return { "webcam" : self.webcam_enabled, "webcam.encodings" : self.webcam_encodings, @@ -50,7 +51,7 @@ def get_server_features(self, _source) -> dict: } - def get_info(self, _proto) -> dict: + def get_info(self, _proto) -> Dict[str,Any]: info = { "" : self.webcam_enabled, } diff --git a/xpra/server/mixins/window_server.py b/xpra/server/mixins/window_server.py index 85f515b680..44e1b2fe81 100644 --- a/xpra/server/mixins/window_server.py +++ b/xpra/server/mixins/window_server.py @@ -1,10 +1,12 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2019 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. #pylint: disable-msg=E1101 +from typing import Dict, Any + from xpra.util import typedict from xpra.server.mixins.stub_server_mixin import StubServerMixin from xpra.server.source.windows_mixin import WindowsMixin @@ -31,7 +33,7 @@ def __init__(self): self.window_min_size = 0, 0 self.window_max_size = 2**15-1, 2**15-1 - def init(self, opts): + def init(self, opts) -> None: def parse_window_size(v, default_value=(0, 0)): try: #split on "," or "x": @@ -74,13 +76,13 @@ def last_client_exited(self): self._focus(None, 0, []) - def get_server_features(self, _source) -> dict: + def get_server_features(self, _source) -> Dict[str,Any]: return { "window_refresh_config" : True, #v4 clients assume this is available "window-filters" : True, #v4 clients assume this is available } - def get_info(self, _proto) -> dict: + def get_info(self, _proto) -> Dict[str,Any]: return { "state" : { "windows" : sum(int(window.is_managed()) for window in tuple(self._id_to_window.values())), @@ -88,7 +90,7 @@ def get_info(self, _proto) -> dict: "filters" : tuple((uuid,repr(f)) for uuid, f in self.window_filters), } - def get_ui_info(self, _proto, _client_uuids=None, wids=None, *_args) -> dict: + def get_ui_info(self, _proto, _client_uuids=None, wids=None, *_args) -> Dict[str,Any]: """ info that must be collected from the UI thread (ie: things that query the display) """ @@ -143,7 +145,7 @@ def is_shown(self, _window) -> bool: return True - def get_window_id(self, _gdkwindow): + def get_window_id(self, _gdkwindow) -> int: #the X11 server can find the model from the window's xid return 0 @@ -160,7 +162,7 @@ def get_windows_info(self, window_ids): info[wid] = self.get_window_info(window) return info - def get_window_info(self, window): + def get_window_info(self, window) -> Dict[str,Any]: from xpra.server.window.metadata import make_window_metadata info = {} for prop in window.get_property_names(): @@ -250,7 +252,7 @@ def _do_send_new_window_packet(self, ptype, window, geometry): y += dy ss.new_window(ptype, wid, window, x, y, w, h, wprops) - def _process_damage_sequence(self, proto, packet): + def _process_damage_sequence(self, proto, packet) -> None: packet_sequence, wid, width, height, decode_time = packet[1:6] if len(packet)>=7: message = packet[6] @@ -260,18 +262,18 @@ def _process_damage_sequence(self, proto, packet): if ss: ss.client_ack_damage(packet_sequence, wid, width, height, decode_time, message) - def refresh_window(self, window): + def refresh_window(self, window) -> None: ww, wh = window.get_dimensions() self.refresh_window_area(window, 0, 0, ww, wh) - def refresh_window_area(self, window, x, y, width, height, options=None): + def refresh_window_area(self, window, x, y, width, height, options=None) -> None: wid = self._window_to_id[window] for ss in tuple(self._server_sources.values()): damage = getattr(ss, "damage", None) if damage: damage(wid, window, x, y, width, height, options) - def _process_buffer_refresh(self, proto, packet): + def _process_buffer_refresh(self, proto, packet) -> None: """ can be used for requesting a refresh, or tuning batch config, or both """ wid, _, qual = packet[1:4] if len(packet)>=6: @@ -301,7 +303,7 @@ def _process_buffer_refresh(self, proto, packet): self._refresh_windows(proto, wid_windows, refresh_opts) - def update_batch_config(self, proto, wid_windows, batch_props, client_properties): + def update_batch_config(self, proto, wid_windows, batch_props, client_properties) -> None: ss = self.get_server_source(proto) if ss is None: return @@ -311,12 +313,12 @@ def update_batch_config(self, proto, wid_windows, batch_props, client_properties self._set_client_properties(proto, wid, window, client_properties) ss.update_batch(wid, window, batch_props) - def _refresh_windows(self, proto, wid_windows, opts=None): + def _refresh_windows(self, proto, wid_windows, opts=None) -> None: ss = self.get_server_source(proto) if ss: self.do_refresh_windows(ss, wid_windows, opts) - def do_refresh_windows(self, ss, wid_windows, opts=None): + def do_refresh_windows(self, ss, wid_windows, opts=None) -> None: for wid, window in wid_windows.items(): if window is None or not window.is_managed(): continue @@ -325,10 +327,10 @@ def do_refresh_windows(self, ss, wid_windows, opts=None): continue ss.refresh(wid, window, opts) - def _idle_refresh_all_windows(self, proto): + def _idle_refresh_all_windows(self, proto) -> None: self.idle_add(self._refresh_windows, proto, self._id_to_window, {}) - def refresh_all_windows(self): + def refresh_all_windows(self) -> None: for ss in tuple(self._server_sources.values()): if not isinstance(ss, WindowsMixin): self.do_refresh_windows(ss, self._id_to_window) @@ -349,19 +351,19 @@ def _window_mapped_at(self, proto, wid, window, coords=None): ss.unmap_window(wid, window) - def _process_map_window(self, proto, packet): + def _process_map_window(self, proto, packet) -> None: log.info("_process_map_window(%s, %s)", proto, packet) - def _process_unmap_window(self, proto, packet): + def _process_unmap_window(self, proto, packet) -> None: log.info("_process_unmap_window(%s, %s)", proto, packet) - def _process_close_window(self, proto, packet): + def _process_close_window(self, proto, packet) -> None: log.info("_process_close_window(%s, %s)", proto, packet) - def _process_configure_window(self, proto, packet): + def _process_configure_window(self, proto, packet) -> None: log.info("_process_configure_window(%s, %s)", proto, packet) - def _get_window_dict(self, wids) -> dict: + def _get_window_dict(self, wids) -> Dict[int,Any]: wd = {} for wid in wids: window = self._id_to_window.get(wid) @@ -369,7 +371,7 @@ def _get_window_dict(self, wids) -> dict: wd[wid] = window return wd - def _process_suspend(self, proto, packet): + def _process_suspend(self, proto, packet) -> None: eventslog("suspend(%s)", packet[1:]) ui = bool(packet[1]) wd = self._get_window_dict(packet[2]) @@ -377,7 +379,7 @@ def _process_suspend(self, proto, packet): if ss: ss.suspend(ui, wd) - def _process_resume(self, proto, packet): + def _process_resume(self, proto, packet) -> None: eventslog("resume(%s)", packet[1:]) ui = bool(packet[1]) wd = self._get_window_dict(packet[2]) @@ -386,17 +388,17 @@ def _process_resume(self, proto, packet): ss.resume(ui, wd) - def send_initial_windows(self, ss, sharing=False): + def send_initial_windows(self, ss, sharing=False) -> None: raise NotImplementedError() - def send_initial_cursors(self, ss, sharing=False): + def send_initial_cursors(self, ss, sharing=False) -> None: pass ###################################################################### # focus: - def _process_focus(self, proto, packet): + def _process_focus(self, proto, packet) -> None: if self.readonly: return wid = packet[1] @@ -412,7 +414,7 @@ def _process_focus(self, proto, packet): if wid>0: ss.user_event() - def _focus(self, _server_source, wid, modifiers): + def _focus(self, _server_source, wid, modifiers) -> None: focuslog("_focus(%s,%s)", wid, modifiers) def get_focus(self) -> int: @@ -422,7 +424,7 @@ def get_focus(self) -> int: return -1 - def init_packet_handlers(self): + def init_packet_handlers(self) -> None: self.add_packet_handlers({ "map-window" : self._process_map_window, "unmap-window" : self._process_unmap_window, diff --git a/xpra/server/pam.pyx b/xpra/server/pam.pyx index 6498eb464a..b50fe95e13 100644 --- a/xpra/server/pam.pyx +++ b/xpra/server/pam.pyx @@ -1,12 +1,14 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2016-2021 Antoine Martin +# Copyright (C) 2016-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. #!python #cython: boundscheck=False, wraparound=False +from typing import Dict + from xpra.log import Logger log = Logger("util", "auth") @@ -197,7 +199,7 @@ cdef class pam_session: else: log("pam_putenv: %s", name_value) - def get_envlist(self) -> dict: + def get_envlist(self) -> Dict[str,str]: assert self.pam_handle!=NULL cdef char **envlist = pam_getenvlist(self.pam_handle) log("pam_getenvlist: %#x", envlist) diff --git a/xpra/server/proxy/proxy_instance.py b/xpra/server/proxy/proxy_instance.py index c61e3e7f2a..c3409c0565 100644 --- a/xpra/server/proxy/proxy_instance.py +++ b/xpra/server/proxy/proxy_instance.py @@ -1,5 +1,5 @@ # This file is part of Xpra. -# Copyright (C) 2013-2021 Antoine Martin +# Copyright (C) 2013-2023 Antoine Martin # Copyright (C) 2008 Nathaniel Smith # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -7,6 +7,7 @@ import socket from time import sleep, time, monotonic from queue import Queue +from typing import Dict, Any from xpra.net.net_util import get_network_caps from xpra.net.compression import Compressed, compressed_wrapper, MIN_COMPRESS_SIZE @@ -223,13 +224,13 @@ def get_window_info(self) -> dict: return info - def get_connection_info(self) -> dict: + def get_connection_info(self) -> Dict[str,Any]: return { "client" : self.client_protocol.get_info(), "server" : self.server_protocol.get_info(), } - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return {"connection" : self.get_connection_info()} diff --git a/xpra/server/rfb/rfb_source.py b/xpra/server/rfb/rfb_source.py index fab6669108..a5dff837e1 100644 --- a/xpra/server/rfb/rfb_source.py +++ b/xpra/server/rfb/rfb_source.py @@ -1,11 +1,12 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2017-2022 Antoine Martin +# Copyright (C) 2017-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import struct from threading import Event +from typing import Dict, Any from xpra.net.rfb.rfb_const import RFBEncoding from xpra.net.rfb.rfb_encode import ( @@ -42,7 +43,7 @@ def __init__(self, protocol, share=False): self.pixel_format = (32, 24, 0, 1, 255, 255, 255, 16, 8, 0) self.quality = 0 - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return { "protocol" : "rfb", "uuid" : self.uuid, diff --git a/xpra/server/server_base.py b/xpra/server/server_base.py index f1963b65f6..a182459c02 100644 --- a/xpra/server/server_base.py +++ b/xpra/server/server_base.py @@ -1,14 +1,14 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. # Copyright (C) 2011 Serviware (Arthur Huillet, ) -# Copyright (C) 2010-2022 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Copyright (C) 2008 Nathaniel Smith # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import os from time import monotonic -from typing import Type, Dict, Callable +from typing import Type, Dict, Callable, Any from xpra.server.server_core import ServerCore from xpra.server.background_worker import add_work_item @@ -197,11 +197,11 @@ def do_cleanup(self) -> None: ###################################################################### # override http scripts to expose just the current session / display - def get_displays(self) -> dict: + def get_displays(self) -> Dict[str,Any]: from xpra.scripts.main import get_displays #pylint: disable=import-outside-toplevel return get_displays(self.dotxpra, display_names=(os.environ.get("DISPLAY"), )) - def get_xpra_sessions(self) -> dict: + def get_xpra_sessions(self) -> Dict[str,Any]: from xpra.scripts.main import get_xpra_sessions #pylint: disable=import-outside-toplevel return get_xpra_sessions(self.dotxpra, matching_display=os.environ.get("DISPLAY")) @@ -226,7 +226,7 @@ def _process_shutdown_server(self, _proto, _packet=()) -> None: self.timeout_add(500, self.clean_quit) - def get_mdns_info(self) -> dict: + def get_mdns_info(self) -> Dict[str,Any]: mdns_info = ServerCore.get_mdns_info(self) if MDNS_CLIENT_COUNT: mdns_info["clients"] = len(self._server_sources) @@ -517,7 +517,7 @@ def update_all_server_settings(self, reset=False) -> None: ###################################################################### # hello: - def get_server_features(self, server_source=None) -> dict: + def get_server_features(self, server_source=None) -> Dict[str,Any]: #these are flags that have been added over time with new versions #to expose new server features: f = { @@ -528,7 +528,7 @@ def get_server_features(self, server_source=None) -> dict: merge_dicts(f, c.get_server_features(self, server_source)) return f - def make_hello(self, source) -> dict: + def make_hello(self, source) -> Dict[str,Any]: capabilities = super().make_hello(source) for c in SERVER_BASES: if c!=ServerCore: @@ -638,7 +638,7 @@ def cb(proto, info): proto._conn, (end-start)*1000) self.get_all_info(cb, proto, None) - def get_ui_info(self, proto, client_uuids=None, *args) -> dict: + def get_ui_info(self, proto, client_uuids=None, *args) -> Dict[str,Any]: """ info that must be collected from the UI thread (ie: things that query the display) """ @@ -655,7 +655,7 @@ def get_ui_info(self, proto, client_uuids=None, *args) -> dict: return info - def get_info(self, proto=None, client_uuids=None) -> dict: + def get_info(self, proto=None, client_uuids=None) -> Dict[str,Any]: log("ServerBase.get_info%s", (proto, client_uuids)) start = monotonic() if client_uuids: @@ -667,7 +667,7 @@ def get_info(self, proto=None, client_uuids=None) -> dict: log("ServerBase.get_info took %.1fms", 1000.0*(monotonic()-start)) return info - def get_packet_handlers_info(self) -> dict: + def get_packet_handlers_info(self) -> Dict[str,Any]: info = ServerCore.get_packet_handlers_info(self) info.update({ "authenticated" : sorted(self._authenticated_packet_handlers.keys()), @@ -676,7 +676,7 @@ def get_packet_handlers_info(self) -> dict: return info - def get_features_info(self) -> dict: + def get_features_info(self) -> Dict[str,Any]: i = { "sharing" : self.sharing is not False, "idle_timeout" : self.idle_timeout, @@ -684,7 +684,7 @@ def get_features_info(self) -> dict: i.update(self.get_server_features()) return i - def do_get_info(self, proto, server_sources=None) -> dict: + def do_get_info(self, proto, server_sources=None) -> Dict[str,Any]: log("ServerBase.do_get_info%s", (proto, server_sources)) start = monotonic() info = {} @@ -804,12 +804,12 @@ def _process_lock_toggle(self, proto, packet) -> None: ###################################################################### # http server and http audio stream: - def get_http_info(self) -> dict: + def get_http_info(self) -> Dict[str,Any]: info = ServerCore.get_http_info(self) info["clients"] = len(self._server_sources) return info - def get_http_scripts(self) -> dict: + def get_http_scripts(self) -> Dict[str,Any]: scripts = {} for c in SERVER_BASES: scripts.update(c.get_http_scripts(self)) diff --git a/xpra/server/server_core.py b/xpra/server/server_core.py index 7a51401dfa..ac0b769964 100644 --- a/xpra/server/server_core.py +++ b/xpra/server/server_core.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. # Copyright (C) 2011 Serviware (Arthur Huillet, ) -# Copyright (C) 2010-2022 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Copyright (C) 2008 Nathaniel Smith # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -17,7 +17,7 @@ from weakref import WeakKeyDictionary from time import sleep, time, monotonic from threading import Thread, Lock -from typing import Callable, List +from typing import Callable, List, Dict, Any from xpra.version_util import ( XPRA_VERSION, vparts, version_str, full_version_str, version_compat_check, get_version_info, @@ -953,7 +953,7 @@ def get_mdns_socktypes(self, socktype:str) -> tuple: socktypes = ["ssh"] return tuple(socktypes) - def get_mdns_info(self) -> dict: + def get_mdns_info(self) -> Dict[str,Any]: mdns_info = { "display" : self.display_name, "username" : get_username(), @@ -1320,7 +1320,7 @@ def ssl_wrap(): t = self.timeout_add(self._rfb_upgrade*1000, self.try_upgrade_to_rfb, proto) self.socket_rfb_upgrade_timer[proto] = t - def get_ssl_socket_options(self, socket_options) -> dict: + def get_ssl_socket_options(self, socket_options) -> Dict[str,Any]: ssllog("get_ssl_socket_options(%s)", socket_options) kwargs = dict((k.replace("-", "_"), v) for k,v in self._ssl_attributes.items()) for k,v in socket_options.items(): @@ -1629,10 +1629,10 @@ def new_websocket_client(wsh): wslog("error closing connection following error: %s", ce) - def get_http_scripts(self) -> dict: + def get_http_scripts(self) -> Dict[str,Any]: return self._http_scripts - def http_query_dict(self, path) -> dict: + def http_query_dict(self, path) -> Dict[str,Any]: return dict(parse_qsl(urlparse(path).query)) def send_json_response(self, data): @@ -1719,7 +1719,7 @@ def http_displays_request(self, path): displays_info = self._filter_display_dict(displays, "state", "wmname", "xpra-server-mode") return self.send_json_response(displays_info) - def get_displays(self) -> dict: + def get_displays(self) -> Dict[str,Any]: from xpra.scripts.main import get_displays_info #pylint: disable=import-outside-toplevel return get_displays_info(self.dotxpra) @@ -1728,14 +1728,14 @@ def http_sessions_request(self, path): sessions_info = self._filter_display_dict(sessions, "state", "username", "session-type", "session-name", "uuid") return self.send_json_response(sessions_info) - def get_xpra_sessions(self) -> dict: + def get_xpra_sessions(self) -> Dict[str,Any]: from xpra.scripts.main import get_xpra_sessions #pylint: disable=import-outside-toplevel return get_xpra_sessions(self.dotxpra) def http_info_request(self, path): return self.send_json_response(self.get_http_info()) - def get_http_info(self) -> dict: + def get_http_info(self) -> Dict[str,Any]: return { "mode" : self.get_server_mode(), "type" : "Python", @@ -2092,7 +2092,7 @@ def auth_verified(self, proto:SocketProtocol, caps:typedict, auth_caps:dict) -> self.idle_add(self.call_hello_oked, proto, caps, auth_caps) - def setup_encryption(self, proto:SocketProtocol, c : typedict) -> dict: + def setup_encryption(self, proto:SocketProtocol, c : typedict) -> Dict[str,Any]: def auth_failed(msg): self.auth_failed(proto, msg) return None @@ -2257,7 +2257,7 @@ def server_idle_timedout(self) -> None: self.clean_quit(False) - def make_hello(self, source=None) -> dict: + def make_hello(self, source=None) -> Dict[str,Any]: now = time() ncaps = get_network_caps(FULL_INFO) ncaps.update(proto_crypto_caps(None if source is None else source.protocol)) @@ -2297,7 +2297,7 @@ def send_id_info(self, proto:SocketProtocol) -> None: log("id info request from %s", proto._conn) proto.send_now(("hello", self.get_session_id_info())) - def get_session_id_info(self) -> dict: + def get_session_id_info(self) -> Dict[str,Any]: #minimal information for identifying the session id_info = { "session-type" : self.session_type, @@ -2347,10 +2347,10 @@ def get_ui_info(self, _proto:SocketProtocol, *_args) -> dict: #this function is for info which MUST be collected from the UI thread return {} - def get_thread_info(self, proto:SocketProtocol) -> dict: + def get_thread_info(self, proto:SocketProtocol) -> Dict[str,Any]: return get_thread_info(proto) - def get_minimal_server_info(self) -> dict: + def get_minimal_server_info(self) -> Dict[str,Any]: return { "mode" : self.get_server_mode(), "session-type" : self.session_type, @@ -2358,7 +2358,7 @@ def get_minimal_server_info(self) -> dict: "machine-id" : get_machine_id(), } - def get_server_info(self) -> dict: + def get_server_info(self) -> Dict[str,Any]: #this function is for non UI thread info info = get_server_info() now = time() @@ -2371,7 +2371,7 @@ def get_server_info(self) -> dict: }) return info - def get_server_load_info(self) -> dict: + def get_server_load_info(self) -> Dict[str,Any]: if POSIX: try: return {"load" : tuple(int(x*1000) for x in os.getloadavg())} @@ -2379,7 +2379,7 @@ def get_server_load_info(self) -> dict: log("cannot get load average", exc_info=True) return {} - def get_server_exec_info(self) -> dict: + def get_server_exec_info(self) -> Dict[str,Any]: info = { "argv" : sys.argv, "path" : sys.path, @@ -2400,7 +2400,7 @@ def get_server_exec_info(self) -> dict: info["original-desktop-display"] = self.original_desktop_display return info - def get_info(self, proto, *_args) -> dict: + def get_info(self, proto, *_args) -> Dict[str,Any]: start = monotonic() #this function is for non UI thread info info = {} @@ -2454,12 +2454,12 @@ def up(prefix, d): log("ServerCore.get_info took %ims", (end-start)*1000) return info - def get_packet_handlers_info(self) -> dict: + def get_packet_handlers_info(self) -> Dict[str,Any]: return { "default" : sorted(self._default_packet_handlers.keys()), } - def get_socket_info(self) -> dict: + def get_socket_info(self) -> Dict[str,Any]: si = {} def add_listener(socktype, info): si.setdefault(socktype, {}).setdefault("listeners", []).append(info) diff --git a/xpra/server/shadow/root_window_model.py b/xpra/server/shadow/root_window_model.py index e69949e7da..9eef058834 100644 --- a/xpra/server/shadow/root_window_model.py +++ b/xpra/server/shadow/root_window_model.py @@ -1,11 +1,12 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2012-2022 Antoine Martin +# Copyright (C) 2012-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import socket from collections import namedtuple +from typing import Dict, Any from xpra.os_util import ( get_generic_os_name, do_get_generic_os_name, @@ -67,7 +68,7 @@ def __init__(self, root_window, capture=None, title="", geometry=None): def __repr__(self): return f"RootWindowModel({self.capture} : {str(self.geometry):24})" - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = {} c = self.capture if c: diff --git a/xpra/server/source/audio_mixin.py b/xpra/server/source/audio_mixin.py index 009906c6d3..eab5d7404c 100644 --- a/xpra/server/source/audio_mixin.py +++ b/xpra/server/source/audio_mixin.py @@ -7,6 +7,7 @@ import os import subprocess from shutil import which +from typing import Dict, Any from xpra.net.compression import Compressed from xpra.server.source.stub_source_mixin import StubSourceMixin @@ -119,7 +120,7 @@ def parse_client_caps(self, c): self.pulseaudio_id, self.pulseaudio_cookie_hash, self.pulseaudio_server, self.audio_decoders, self.audio_encoders, self.audio_receive, self.audio_send) - def get_caps(self) -> dict: + def get_caps(self) -> Dict[str,Any]: if not self.wants_audio or not self.audio_properties: return {} audio_props = self.audio_properties.copy() @@ -547,10 +548,10 @@ def get_audio_source_latency(self): return encoder_latency - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return {"audio" : self.get_audio_info()} - def get_audio_info(self) -> dict: + def get_audio_info(self) -> Dict[str,Any]: def audio_info(supported, prop, codecs): i = {"codecs" : codecs} if not supported: diff --git a/xpra/server/source/avsync_mixin.py b/xpra/server/source/avsync_mixin.py index c51dd8573e..0c0a32eb29 100644 --- a/xpra/server/source/avsync_mixin.py +++ b/xpra/server/source/avsync_mixin.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2020 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. +from typing import Dict, Any + from xpra.util import envint, typedict from xpra.server.source.stub_source_mixin import StubSourceMixin from xpra.log import Logger @@ -46,7 +48,7 @@ def init_state(self): self.av_sync_delta = AV_SYNC_DELTA - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return { "av-sync" : { "" : self.av_sync, diff --git a/xpra/server/source/client_connection.py b/xpra/server/source/client_connection.py index d79fe46166..ed448cfe5e 100644 --- a/xpra/server/source/client_connection.py +++ b/xpra/server/source/client_connection.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. # Copyright (C) 2011 Serviware (Arthur Huillet, ) -# Copyright (C) 2010-2022 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Copyright (C) 2008 Nathaniel Smith # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import sys +from typing import Dict, Any from time import sleep, monotonic from threading import Event from collections import deque @@ -346,7 +347,7 @@ def send_async(self, *parts, **kwargs): ###################################################################### # info: - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: if not FULL_INFO: return {"protocol" : "xpra"} info = { diff --git a/xpra/server/source/client_connection_factory.py b/xpra/server/source/client_connection_factory.py index 33c8d0547d..08989c508f 100644 --- a/xpra/server/source/client_connection_factory.py +++ b/xpra/server/source/client_connection_factory.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2020 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. +from typing import Dict, Any + from xpra.server import server_features from xpra.util import merge_dicts, typedict, print_nested_dict from xpra.common import LOG_HELLO @@ -120,7 +122,7 @@ def send_hello(self, server_capabilities): self.send("hello", capabilities) self.hello_sent = True - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: def module_name(m): name = str(m.__name__.split(".")[-1]) return name.replace("Mixin", "").replace("Connection", "").rstrip("_") diff --git a/xpra/server/source/clipboard_connection.py b/xpra/server/source/clipboard_connection.py index 57ab6d398a..af1bae67e0 100644 --- a/xpra/server/source/clipboard_connection.py +++ b/xpra/server/source/clipboard_connection.py @@ -1,11 +1,12 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2022 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Copyright (C) 2008 Nathaniel Smith # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. from time import monotonic +from typing import Dict, Any from collections import deque from xpra.server.source.stub_source_mixin import StubSourceMixin @@ -63,7 +64,7 @@ def parse_client_caps(self, c : typedict): log("client clipboard: greedy=%s, want_targets=%s, selections=%s", self.clipboard_greedy, self.clipboard_want_targets, self.clipboard_selections) - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return { "clipboard" : { "enabled" : self.clipboard_enabled, diff --git a/xpra/server/source/encodings_mixin.py b/xpra/server/source/encodings_mixin.py index 85d1a7b95a..7992c4762e 100644 --- a/xpra/server/source/encodings_mixin.py +++ b/xpra/server/source/encodings_mixin.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. # Copyright (C) 2011 Serviware (Arthur Huillet, ) -# Copyright (C) 2010-2021 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import os from math import sqrt +from typing import Dict, Any from time import sleep, monotonic from xpra.server.source.stub_source_mixin import StubSourceMixin @@ -106,7 +107,7 @@ def all_window_sources(self): return tuple(window_sources.values()) - def get_caps(self) -> dict: + def get_caps(self) -> Dict[str,Any]: caps = {} if "encodings" in self.wants and self.encoding: caps["encoding"] = self.encoding @@ -471,7 +472,7 @@ def set_encoding(self, encoding : str, window_ids, strict=False): self.encoding = encoding - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = { "auto_refresh" : self.auto_refresh_delay, "lz4" : self.lz4, diff --git a/xpra/server/source/fileprint_mixin.py b/xpra/server/source/fileprint_mixin.py index f3fceba085..e5340db622 100644 --- a/xpra/server/source/fileprint_mixin.py +++ b/xpra/server/source/fileprint_mixin.py @@ -1,10 +1,11 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2021 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import os +from typing import Dict, Any from xpra.util import envbool, typedict, net_utf8 from xpra.os_util import get_machine_id @@ -38,7 +39,7 @@ def parse_client_caps(self, c : typedict): FileTransferHandler.parse_file_transfer_caps(self, c) self.machine_id = c.strget("machine_id") - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return { "printers" : self.printers, "file-transfers" : FileTransferHandler.get_info(self), diff --git a/xpra/server/source/idle_mixin.py b/xpra/server/source/idle_mixin.py index abf2e2756f..12280ff44a 100644 --- a/xpra/server/source/idle_mixin.py +++ b/xpra/server/source/idle_mixin.py @@ -1,10 +1,12 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2020 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. from time import monotonic +from typing import Dict, Any + from xpra.util import envint, typedict, ConnectionMessage, NotificationID from xpra.server.source.stub_source_mixin import StubSourceMixin from xpra.log import Logger @@ -45,7 +47,7 @@ def cleanup(self): self.cancel_idle_grace_timeout() self.cancel_idle_timeout() - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return { "idle_time" : int(monotonic()-self.last_user_event), "idle" : self.idle, diff --git a/xpra/server/source/input_mixin.py b/xpra/server/source/input_mixin.py index b60de53458..4c4962f7ad 100644 --- a/xpra/server/source/input_mixin.py +++ b/xpra/server/source/input_mixin.py @@ -5,7 +5,7 @@ # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. -from typing import Tuple, Optional, Any +from typing import Tuple, Optional, Dict, Any from xpra.server.source.stub_source_mixin import StubSourceMixin from xpra.keyboard.mask import DEFAULT_MODIFIER_MEANINGS @@ -53,7 +53,7 @@ def parse_client_caps(self, c : typedict): self.mouse_last_position = c.intpair("mouse.initial-position") - def get_info(self) -> dict[str,Any]: + def get_info(self) -> Dict[str,Any]: dc_info : dict[str,Any] = {} dct = self.double_click_time if dct: @@ -69,7 +69,7 @@ def get_info(self) -> dict[str,Any]: info["keyboard"] = kc.get_info() return info - def get_caps(self) -> dict[str,Any]: + def get_caps(self) -> Dict[str,Any]: #expose the "modifier_client_keycodes" defined in the X11 server keyboard config object, #so clients can figure out which modifiers map to which keys: kc = self.keyboard_config diff --git a/xpra/server/source/mmap_connection.py b/xpra/server/source/mmap_connection.py index d68db87cfe..d1c4df6384 100644 --- a/xpra/server/source/mmap_connection.py +++ b/xpra/server/source/mmap_connection.py @@ -5,6 +5,7 @@ # later version. See the file COPYING for details. from random import randint +from typing import Dict, Any from xpra.util import typedict from xpra.server.source.stub_source_mixin import StubSourceMixin @@ -126,7 +127,7 @@ def parse_client_caps(self, c : typedict): from xpra.simple_stats import std_unit log.info(" mmap is enabled using %sB area in %s", std_unit(self.mmap_size, unit=1024), mmap_filename) - def get_caps(self) -> dict: + def get_caps(self) -> Dict[str,Any]: caps : dict [str, object] = {} sep = "." if self.mmap_client_namespace else "_" def mmapattr(name, value): @@ -140,7 +141,7 @@ def mmapattr(name, value): mmapattr("token_bytes", self.mmap_client_token_bytes) return caps - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return { "mmap" : { "supported" : self.supports_mmap, diff --git a/xpra/server/source/notification_mixin.py b/xpra/server/source/notification_mixin.py index 110db3326f..a955c0ccac 100644 --- a/xpra/server/source/notification_mixin.py +++ b/xpra/server/source/notification_mixin.py @@ -5,6 +5,8 @@ # later version. See the file COPYING for details. from xpra.util import typedict +from typing import Dict, Any + from xpra.server.source.stub_source_mixin import StubSourceMixin from xpra.log import Logger @@ -39,7 +41,7 @@ def parse_client_caps(self, c : typedict): self.send_notifications_actions = c.boolget("notifications.actions") log("notifications=%s, actions=%s", self.send_notifications, self.send_notifications_actions) - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return { "notifications" : self.send_notifications, } diff --git a/xpra/server/source/shell_mixin.py b/xpra/server/source/shell_mixin.py index bc9500ca39..41c1bca109 100644 --- a/xpra/server/source/shell_mixin.py +++ b/xpra/server/source/shell_mixin.py @@ -1,10 +1,11 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2020 Antoine Martin +# Copyright (C) 2020-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import io +from typing import Dict, Any from contextlib import redirect_stdout, redirect_stderr from xpra.util import typedict @@ -39,10 +40,10 @@ def init_from(self, protocol, server): self.shell_enabled = False log("init_from(%s, %s) shell_enabled(%s)=%s", protocol, server, options, self.shell_enabled) - def get_caps(self) -> dict: + def get_caps(self) -> Dict[str,Any]: return {"shell" : self.shell_enabled} - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return {"shell" : self.shell_enabled} def shell_exec(self, code): diff --git a/xpra/server/source/source_stats.py b/xpra/server/source/source_stats.py index ba0a7446e3..ff095297ee 100644 --- a/xpra/server/source/source_stats.py +++ b/xpra/server/source/source_stats.py @@ -8,6 +8,7 @@ from math import sqrt from time import monotonic +from typing import Dict, Any from collections import deque from xpra.server.cystats import ( #@UnresolvedImport @@ -210,7 +211,7 @@ def mayaddfac(metric, info, factor, weight): mayaddfac("congestion", {}, 1+self.congestion_value, self.congestion_value*10) return factors - def get_connection_info(self) -> dict: + def get_connection_info(self) -> Dict[str,Any]: latencies = tuple(int(x*1000) for (_, _, _, x) in tuple(self.client_latency)) now = monotonic() info = { @@ -232,7 +233,7 @@ def get_connection_info(self) -> dict: return info - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: cwqsizes = tuple(x[1] for x in tuple(self.compression_work_qsizes)) pqsizes = tuple(x[1] for x in tuple(self.packet_qsizes)) now = monotonic() diff --git a/xpra/server/source/stub_source_mixin.py b/xpra/server/source/stub_source_mixin.py index cf5ecd0404..b49e37a8ce 100644 --- a/xpra/server/source/stub_source_mixin.py +++ b/xpra/server/source/stub_source_mixin.py @@ -1,9 +1,10 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2018-2020 Antoine Martin +# Copyright (C) 2018-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. +from typing import Dict, Any from xpra.util import typedict class StubSourceMixin: @@ -45,13 +46,13 @@ def parse_client_caps(self, c : typedict): Parse client attributes specified in the hello capabilities. """ - def get_caps(self) -> dict: + def get_caps(self) -> Dict[str,Any]: """ Return the capabilities provided by this mixin. """ return {} - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: """ Runtime information on this mixin, includes state and settings. Somewhat overlaps with the capabilities, diff --git a/xpra/server/source/webcam_mixin.py b/xpra/server/source/webcam_mixin.py index df61faf3bf..1399a9f98d 100644 --- a/xpra/server/source/webcam_mixin.py +++ b/xpra/server/source/webcam_mixin.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2022 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. +from typing import Dict, Any + from xpra.os_util import POSIX, OSX, bytestostr from xpra.util import envint, csv, typedict from xpra.server.source.stub_source_mixin import StubSourceMixin @@ -68,7 +70,7 @@ def cleanup(self): self.stop_all_virtual_webcams() - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: return { "webcam" : { "encodings" : self.webcam_encodings, diff --git a/xpra/server/source/windows_mixin.py b/xpra/server/source/windows_mixin.py index 7c9708835f..c0bd6f79b2 100644 --- a/xpra/server/source/windows_mixin.py +++ b/xpra/server/source/windows_mixin.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2022 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Copyright (C) 2008 Nathaniel Smith # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -8,6 +8,7 @@ import os from io import BytesIO from time import monotonic +from typing import Dict, Any try: from PIL import Image @@ -161,13 +162,13 @@ def parse_client_caps(self, c): filterslog.error("Error parsing window-filters: %s", e) - def get_caps(self) -> dict: + def get_caps(self) -> Dict[str,Any]: return {} ###################################################################### # info: - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = { "windows" : self.send_windows, "cursors" : self.send_cursors, @@ -187,7 +188,7 @@ def get_info(self) -> dict: info.update(self.get_window_info()) return info - def get_window_info(self) -> dict: + def get_window_info(self) -> Dict[str,Any]: """ Adds encoding and window specific information """ diff --git a/xpra/server/window/metadata.py b/xpra/server/window/metadata.py index 218ec71d39..d35b7bbd36 100644 --- a/xpra/server/window/metadata.py +++ b/xpra/server/window/metadata.py @@ -1,19 +1,20 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2021 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Copyright (C) 2008 Nathaniel Smith # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import os import socket +from typing import Dict, Any from xpra.util import WORKSPACE_UNSET, get_util_logger SKIP_METADATA = os.environ.get("XPRA_SKIP_METADATA", "").split(",") -def make_window_metadata(window, propname, get_window_id=None, skip_defaults=False) -> dict: +def make_window_metadata(window, propname, get_window_id=None, skip_defaults=False) -> Dict[str,Any]: try: return do_make_window_metadata(window, propname, get_window_id, skip_defaults) except (ValueError, TypeError) as e: @@ -27,7 +28,7 @@ def make_window_metadata(window, propname, get_window_id=None, skip_defaults=Fal return {} -def do_make_window_metadata(window, propname, get_window_id=None, skip_defaults=False) -> dict: +def do_make_window_metadata(window, propname, get_window_id=None, skip_defaults=False) -> Dict[str,Any]: if propname in SKIP_METADATA: return {} #note: some of the properties handled here aren't exported to the clients, diff --git a/xpra/server/window/video_subregion.py b/xpra/server/window/video_subregion.py index 53e8fdee68..3b43ccf8b6 100644 --- a/xpra/server/window/video_subregion.py +++ b/xpra/server/window/video_subregion.py @@ -1,11 +1,12 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2013-2021 Antoine Martin +# Copyright (C) 2013-2023 Antoine Martin # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import math from time import monotonic +from typing import Dict, Any from xpra.util import envint, envbool from xpra.rectangle import rectangle, add_rectangle, remove_rectangle, merge_all #@UnresolvedImport @@ -136,7 +137,7 @@ def cancel_refresh_timer(self): self.refresh_timer = 0 self.source_remove(rt) - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: r = self.rectangle info = { "supported" : self.supported, diff --git a/xpra/server/window/window_source.py b/xpra/server/window/window_source.py index a3f5aa084b..d3fa100ad3 100644 --- a/xpra/server/window/window_source.py +++ b/xpra/server/window/window_source.py @@ -12,7 +12,7 @@ from math import sqrt, ceil from collections import deque from time import monotonic -from typing import Callable, Dict, List, Tuple, Iterable, ContextManager +from typing import Callable, Dict, List, Tuple, Iterable, ContextManager, Any from xpra.os_util import bytestostr, POSIX, OSX, DummyContextManager from xpra.util import envint, envbool, csv, typedict, first_time, decode_str, repr_ellipsized @@ -508,7 +508,7 @@ def ui_cleanup(self) -> None: self.global_statistics = None - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: #should get prefixed with "client[M].window[N]." by caller """ Add window specific stats diff --git a/xpra/server/window/window_stats.py b/xpra/server/window/window_stats.py index b582460839..cefbd3b621 100644 --- a/xpra/server/window/window_stats.py +++ b/xpra/server/window/window_stats.py @@ -8,6 +8,7 @@ from math import sqrt from time import monotonic +from typing import Dict, Any from collections import deque from xpra.simple_stats import get_list_stats, get_weighted_list_stats @@ -166,7 +167,7 @@ def mayaddfac(metric, info, factor, weight): return factors - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = {"damage" : {"events" : self.damage_events_count, "packets_sent" : self.packet_count, "target-latency" : int(1000*self.target_latency), diff --git a/xpra/server/window/window_video_source.py b/xpra/server/window/window_video_source.py index 4ad698676b..1d427cf1c8 100644 --- a/xpra/server/window/window_video_source.py +++ b/xpra/server/window/window_video_source.py @@ -11,7 +11,7 @@ from math import sqrt, ceil from functools import reduce from time import monotonic -from typing import Callable, Tuple +from typing import Callable, Tuple, Dict, Any from xpra.net.compression import Compressed, LargeStructure from xpra.codecs.codec_constants import TransientCodecException, RGB_FORMATS, PIXEL_SUBSAMPLING @@ -225,7 +225,7 @@ def update_av_sync_frame_delay(self) -> None: self.may_update_av_sync_delay() - def get_property_info(self) -> dict: + def get_property_info(self) -> Dict[str,Any]: i = super().get_property_info() if self.scaling_control is None: i["scaling.control"] = "auto" @@ -234,7 +234,7 @@ def get_property_info(self) -> dict: i["scaling"] = self.scaling or (1, 1) return i - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: info = super().get_info() sr = self.video_subregion if sr: @@ -279,7 +279,7 @@ def addcinfo(prefix, x): info.setdefault("encoding", {}).update(einfo) return info - def get_pipeline_info(self) -> dict: + def get_pipeline_info(self) -> Dict[str,Any]: lp = self.last_pipeline_params if not lp: return {} @@ -292,7 +292,7 @@ def get_pipeline_info(self) -> dict: def get_pipeline_score_info(self, score, scaling, csc_scaling, csc_width : int, csc_height : int, csc_spec, - enc_in_format, encoder_scaling, enc_width : int, enc_height : int, encoder_spec) -> dict: + enc_in_format, encoder_scaling, enc_width : int, enc_height : int, encoder_spec) -> Dict[str,Any]: def specinfo(x): try: return x.codec_type diff --git a/xpra/server/window/windowicon_source.py b/xpra/server/window/windowicon_source.py index a39467f9fe..a535abde1f 100644 --- a/xpra/server/window/windowicon_source.py +++ b/xpra/server/window/windowicon_source.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. -# Copyright (C) 2010-2022 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Copyright (C) 2008 Nathaniel Smith # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. @@ -9,6 +9,7 @@ import threading from io import BytesIO from time import monotonic +from typing import Dict, Any try: from PIL import Image @@ -79,7 +80,7 @@ def cancel_window_icon_timer(self): self.send_window_icon_timer = 0 self.source_remove(swit) - def get_info(self) -> dict: + def get_info(self) -> Dict[str,Any]: idata = self.window_icon_data if not idata: return {} diff --git a/xpra/util.py b/xpra/util.py index 8abe296fda..cccb537262 100644 --- a/xpra/util.py +++ b/xpra/util.py @@ -789,7 +789,7 @@ def notypedict(d:Dict) -> Dict: d[k] = notypedict(v) return dict(d) -def flatten_dict(info:Dict[str,Any], sep:str=".") -> Dict: +def flatten_dict(info:Dict[str,Any], sep:str=".") -> Dict[str,Any]: to : dict[str, Any] = {} _flatten_dict(to, sep, "", info) return to diff --git a/xpra/x11/bindings/window.pyx b/xpra/x11/bindings/window.pyx index 66226b6238..2eb66bdd88 100644 --- a/xpra/x11/bindings/window.pyx +++ b/xpra/x11/bindings/window.pyx @@ -4,6 +4,7 @@ # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. +from typing import Dict, Any from xpra.gtk_common.error import XError from xpra.x11.bindings.xlib cimport ( @@ -1181,7 +1182,7 @@ cdef class X11WindowBindingsInstance(X11CoreBindingsInstance): return pychildren - def getSizeHints(self, Window xwindow) -> dict: + def getSizeHints(self, Window xwindow) -> Dict[str,Any]: self.context_check("getSizeHints") cdef XSizeHints *size_hints = XAllocSizeHints() cdef long supplied_return #ignored! @@ -1252,7 +1253,7 @@ cdef class X11WindowBindingsInstance(X11CoreBindingsInstance): XSetWMNormalHints(self.display, xwindow, size_hints) XFree(size_hints) - def getWMHints(self, Window xwindow) -> dict: + def getWMHints(self, Window xwindow) -> Dict[str,Any]: self.context_check("getWMHints") cdef XWMHints *wm_hints = XGetWMHints(self.display, xwindow) if wm_hints==NULL: diff --git a/xpra/x11/common.py b/xpra/x11/common.py index c00fbfdb5b..416e108b7b 100644 --- a/xpra/x11/common.py +++ b/xpra/x11/common.py @@ -4,7 +4,7 @@ # later version. See the file COPYING for details. import struct -from typing import Callable, Tuple, Optional, Any +from typing import Callable, Tuple, Optional, Any, Dict from xpra.util import u, ellipsizer from xpra.os_util import hexstr, bytestostr @@ -84,7 +84,7 @@ def get_wm_name() -> str: return "" -def get_icc_data() -> dict: +def get_icc_data() -> Dict[str,Any]: icc = {} try: data = get_X11_root_property("_ICC_PROFILE", "CARDINAL") @@ -246,7 +246,7 @@ def get_xsettings(): from xpra.x11.xsettings_prop import bytes_to_xsettings return bytes_to_xsettings(data) -def xsettings_to_dict(v) -> dict[str, Tuple[int, Any]]: +def xsettings_to_dict(v) -> Dict[str, Tuple[int, Any]]: d : dict[str, Tuple[int, Any]] = {} if v: _, values = v diff --git a/xpra/x11/desktop/desktop_server_base.py b/xpra/x11/desktop/desktop_server_base.py index 6bfdc03095..42a400bc17 100644 --- a/xpra/x11/desktop/desktop_server_base.py +++ b/xpra/x11/desktop/desktop_server_base.py @@ -5,6 +5,7 @@ # later version. See the file COPYING for details. import os +from typing import Dict, Any from gi.repository import GObject, Gdk, Gio # @UnresolvedImport from xpra.util import updict, log_screen_sizes, envbool, csv @@ -102,7 +103,7 @@ def modify_gsettings(self) -> None: "com.deepin.wrap.gnome.desktop.interface" : ("enable-animations",), }) - def do_modify_gsettings(self, defs:dict, value=False) -> dict: + def do_modify_gsettings(self, defs:Dict[str,Any], value=False) -> Dict[str,Any]: modified = {} schemas = Gio.Settings.list_schemas() for schema, attributes in defs.items(): diff --git a/xpra/x11/desktop/monitor_server.py b/xpra/x11/desktop/monitor_server.py index 22571bbaef..ed60b6b67a 100644 --- a/xpra/x11/desktop/monitor_server.py +++ b/xpra/x11/desktop/monitor_server.py @@ -5,6 +5,7 @@ # later version. See the file COPYING for details. import os +from typing import Dict, Any from gi.repository import GObject # @UnresolvedImport from xpra.scripts.config import InitException @@ -57,7 +58,7 @@ def server_init(self) -> None: def get_server_mode(self) -> str: return "X11 monitor" - def make_hello(self, source) -> dict: + def make_hello(self, source) -> Dict[str,Any]: capabilities = super().make_hello(source) if "features" in source.wants: capabilities.update({ @@ -281,7 +282,7 @@ def _adjust_monitor(self, model, delta_x : int, delta_y : int) -> None: }) model.init(mdef) - def get_monitor_config(self) -> dict: + def get_monitor_config(self) -> Dict[int,Dict]: monitor_defs = {} for wid, model in self._id_to_window.items(): monitor = model.get_definition() diff --git a/xpra/x11/gtk_x11/wm_check.py b/xpra/x11/gtk_x11/wm_check.py index 3bbccf8e41..5b05af1031 100644 --- a/xpra/x11/gtk_x11/wm_check.py +++ b/xpra/x11/gtk_x11/wm_check.py @@ -4,6 +4,8 @@ # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. +from typing import Dict, Any + from xpra.util import envbool from xpra.gtk_common.error import xsync, xlog from xpra.x11.gtk_x11.prop import prop_get @@ -16,7 +18,7 @@ _NEW_WM_CM_S0 = "_NEW_WM_CM_S0" FORCE_REPLACE_WM = envbool("XPRA_FORCE_REPLACE_WM", False) -def get_wm_info() -> dict: +def get_wm_info() -> Dict[str,Any]: with xsync: X11Window = X11WindowBindings() root_xid = X11Window.get_root_xid() diff --git a/xpra/x11/models/core.py b/xpra/x11/models/core.py index 41bee9ac92..c9419c29c0 100644 --- a/xpra/x11/models/core.py +++ b/xpra/x11/models/core.py @@ -7,6 +7,7 @@ import os import signal from socket import gethostname +from typing import Dict, Any from gi.repository import GObject # @UnresolvedImport from xpra.util import envbool, first_time @@ -445,7 +446,7 @@ def _scrub_x11(self) -> None: # XShape ######################################### - def _read_xshape(self, x:int=0, y:int=0) -> dict: + def _read_xshape(self, x:int=0, y:int=0) -> Dict[str,Any]: if not X11Window.displayHasXShape() or not XSHAPE: return {} extents = X11Window.XShapeQueryExtents(self.xid) diff --git a/xpra/x11/server.py b/xpra/x11/server.py index 97c0c95b1e..ad9345dcbd 100644 --- a/xpra/x11/server.py +++ b/xpra/x11/server.py @@ -11,6 +11,7 @@ import math from time import monotonic, sleep from collections import deque +from typing import Dict, Any from gi.repository import GObject, Gdk, GdkX11 # @UnresolvedImport from xpra.version_util import XPRA_VERSION @@ -251,7 +252,7 @@ def server_event(self, *args) -> None: self.emit("server-event", args) - def make_hello(self, source) -> dict: + def make_hello(self, source) -> Dict[str,Any]: capabilities = super().make_hello(source) if "features" in source.wants: capabilities["pointer.grabs"] = True @@ -273,7 +274,7 @@ def make_hello(self, source) -> dict: ########################################################################## # info: # - def do_get_info(self, proto, server_sources) -> dict: + def do_get_info(self, proto, server_sources) -> Dict[str,Any]: info = super().do_get_info(proto, server_sources) info["exit-with-windows"] = self._exit_with_windows info.setdefault("state", {}).update({ @@ -282,7 +283,7 @@ def do_get_info(self, proto, server_sources) -> dict: }) return info - def get_ui_info(self, proto, wids=None, *args) -> dict: + def get_ui_info(self, proto, wids=None, *args) -> Dict[str,Any]: info = super().get_ui_info(proto, wids, *args) #_NET_WM_NAME: wm = self._wm @@ -290,7 +291,7 @@ def get_ui_info(self, proto, wids=None, *args) -> dict: info.setdefault("state", {})["window-manager-name"] = wm.get_net_wm_name() return info - def get_window_info(self, window) -> dict: + def get_window_info(self, window) -> Dict[str,Any]: info = super().get_window_info(window) info.update({ "focused" : bool(self._has_focus and self._window_to_id.get(window, -1)==self._has_focus), diff --git a/xpra/x11/shadow_x11_server.py b/xpra/x11/shadow_x11_server.py index 50732aadda..75a58bf368 100755 --- a/xpra/x11/shadow_x11_server.py +++ b/xpra/x11/shadow_x11_server.py @@ -7,6 +7,8 @@ import re from time import monotonic +from typing import Dict, Any + from xpra.x11.x11_server_core import X11ServerCore from xpra.os_util import is_Wayland, get_loaded_kernel_modules from xpra.util import envbool, envint, merge_dicts, AdHocStruct, NotificationID @@ -430,13 +432,13 @@ def verify_capture(self, ss) -> None: ss.may_notify(nid, "Shadow Error", f"Error shadowing the display:\n{e}", icon_name="bugs") - def make_hello(self, source) -> dict: + def make_hello(self, source) -> Dict[str,Any]: capabilities = X11ServerCore.make_hello(self, source) capabilities.update(GTKShadowServerBase.make_hello(self, source)) capabilities["server_type"] = "X11 Shadow" return capabilities - def get_info(self, proto, *_args) -> dict: + def get_info(self, proto, *_args) -> Dict[str,Any]: info = X11ServerCore.get_info(self, proto) merge_dicts(info, ShadowServerBase.get_info(self, proto)) info.setdefault("features", {})["shadow"] = True diff --git a/xpra/x11/x11_server_base.py b/xpra/x11/x11_server_base.py index dd66a7a213..acbf106e32 100644 --- a/xpra/x11/x11_server_base.py +++ b/xpra/x11/x11_server_base.py @@ -1,12 +1,13 @@ # -*- coding: utf-8 -*- # This file is part of Xpra. # Copyright (C) 2011 Serviware (Arthur Huillet, ) -# Copyright (C) 2010-2022 Antoine Martin +# Copyright (C) 2010-2023 Antoine Martin # Copyright (C) 2008 Nathaniel Smith # Xpra is released under the terms of the GNU GPL v2, or, at your option, any # later version. See the file COPYING for details. import os +from typing import Dict, Any from xpra.os_util import bytestostr, strtobytes, hexstr from xpra.util import typedict, envbool @@ -223,7 +224,7 @@ def dpi_changed(self) -> None: self.update_server_settings() - def get_info(self, proto=None, client_uuids=None) -> dict: + def get_info(self, proto=None, client_uuids=None) -> Dict[str,Any]: info = super().get_info(proto=proto, client_uuids=client_uuids) display_info = info.setdefault("display", {}) if self.display_pid: @@ -231,7 +232,7 @@ def get_info(self, proto=None, client_uuids=None) -> dict: display_info["icc"] = self.get_icc_info() return info - def get_icc_info(self) -> dict: + def get_icc_info(self) -> Dict[str,Any]: icc_info = { "sync" : SYNC_ICC, } diff --git a/xpra/x11/x11_server_core.py b/xpra/x11/x11_server_core.py index e50edfb1ad..e472a6ee66 100644 --- a/xpra/x11/x11_server_core.py +++ b/xpra/x11/x11_server_core.py @@ -9,6 +9,7 @@ import os import threading from time import monotonic +from typing import Dict, Any import gi from xpra.x11.bindings.core import set_context_check, X11CoreBindings #@UnresolvedImport @@ -264,7 +265,7 @@ def init_virtual_devices(self, _devices) -> None: self.input_devices = "xtest" - def get_child_env(self) -> dict: + def get_child_env(self) -> Dict[str,str]: #adds fakeXinerama: env = super().get_child_env() if self.fake_xinerama and self.libfakeXinerama_so: @@ -334,7 +335,7 @@ def set_keyboard_repeat(self, key_repeat) -> None: X11Keyboard.set_key_repeat_rate(500, 30) keylog("keyboard repeat disabled") - def make_hello(self, source) -> dict: + def make_hello(self, source) -> Dict[str,Any]: capabilities = super().make_hello(source) capabilities["server_type"] = "Python/gtk/x11" if "features" in source.wants: @@ -372,7 +373,7 @@ def send_initial_cursors(self, ss, sharing:bool=False) -> None: cursorlog.error("Error sending default cursor", exc_info=True) - def do_get_info(self, proto, server_sources) -> dict: + def do_get_info(self, proto, server_sources) -> Dict[str,Any]: start = monotonic() info = super().do_get_info(proto, server_sources) sinfo = info.setdefault("server", {}) @@ -391,7 +392,7 @@ def do_get_info(self, proto, server_sources) -> dict: log("X11ServerCore.do_get_info took %ims", (monotonic()-start)*1000) return info - def get_ui_info(self, proto, wids=None, *args) -> dict: + def get_ui_info(self, proto, wids=None, *args) -> Dict[str,Any]: log("do_get_info thread=%s", threading.current_thread()) info = super().get_ui_info(proto, wids, *args) #this is added here because the server keyboard config doesn't know about "keys_pressed".. @@ -431,7 +432,7 @@ def get_ui_info(self, proto, wids=None, *args) -> dict: return info - def get_cursor_info(self) -> dict: + def get_cursor_info(self) -> Dict[str,Any]: #(NOT from UI thread) #copy to prevent race: cd = self.last_cursor_image @@ -448,7 +449,7 @@ def get_cursor_info(self) -> dict: cinfo[x] = v return cinfo - def get_window_info(self, window) -> dict: + def get_window_info(self, window) -> Dict[str,Any]: info = super().get_window_info(window) info["XShm"] = window.uses_XShm() info["geometry"] = window.get_geometry() @@ -814,7 +815,7 @@ def show_dpi(): return root_w, root_h - def mirror_client_monitor_layout(self) -> dict: + def mirror_client_monitor_layout(self) -> Dict[int,Any]: with xsync: assert RandR.is_dummy16(), "cannot match monitor layout without RandR 1.6" #if we have a single UI client,