Daniel Brötzmann pushed to branch master at gajim / gajim
Commits: 1a09bf93 by wurstsalat at 2022-05-26T20:11:45+02:00 chore: HTTPUpload: Add type annotations
- - - - - ac6b0ae0 by wurstsalat at 2022-05-26T20:12:57+02:00 chore: Annotations: Add type annotations
- - - - - ab9acfb7 by wurstsalat at 2022-05-26T20:52:43+02:00 chore: Bookmarks: Add type annotations
- - - - - 3c9084de by wurstsalat at 2022-05-26T20:52:44+02:00 chore: Blocking: Add type annotations
- - - - - 6feac48c by wurstsalat at 2022-05-26T20:57:35+02:00 chore: SecLabels: Add type annotations
- - - - - 4a04c5aa by wurstsalat at 2022-05-26T21:03:50+02:00 chore: Misc: Add type annotations
- - - - - a6af6369 by wurstsalat at 2022-05-26T21:29:43+02:00 chore: Jingle: Add type annotations
- - - - - 36260318 by wurstsalat at 2022-05-26T21:33:01+02:00 chore: LastActivity: Add type annotations
- - - - - 9f6847d8 by wurstsalat at 2022-05-26T21:37:09+02:00 chore: Carbons: Add type annotations
- - - - - 476b2fd4 by wurstsalat at 2022-05-26T22:13:06+02:00 chore: Chatstates: Add type annotations
- - - - - 085cba6b by wurstsalat at 2022-05-26T22:18:16+02:00 chore: Roster: Add type annotations
- - - - - 231bd80c by wurstsalat at 2022-05-26T22:22:02+02:00 chore: EntityTime: Add type annotations
- - - - - c09d9494 by wurstsalat at 2022-05-26T22:29:57+02:00 chore: RosterItemExchange: Add type annotations
- - - - - 91944ee2 by wurstsalat at 2022-05-26T22:36:13+02:00 chore: UserTune: Add type annotations
- - - - - 9cc7f9ab by wurstsalat at 2022-05-26T22:39:22+02:00 chore: Register: Add type annotations
- - - - - 2191fd9d by wurstsalat at 2022-05-26T22:44:44+02:00 chore: Receipts: Add type annotations
- - - - - c694344b by wurstsalat at 2022-05-26T22:47:17+02:00 chore: Delimiter: Add type annotations
- - - - - 59e9fffa by wurstsalat at 2022-05-26T22:49:54+02:00 chore: UserNickname: Add type annotations
- - - - -
22 changed files:
- gajim/common/events.py - gajim/common/modules/annotations.py - gajim/common/modules/blocking.py - gajim/common/modules/bookmarks.py - gajim/common/modules/carbons.py - gajim/common/modules/chatstates.py - gajim/common/modules/delimiter.py - gajim/common/modules/entity_time.py - gajim/common/modules/httpupload.py - gajim/common/modules/jingle.py - gajim/common/modules/last_activity.py - gajim/common/modules/misc.py - gajim/common/modules/receipts.py - gajim/common/modules/register.py - gajim/common/modules/roster.py - gajim/common/modules/roster_item_exchange.py - gajim/common/modules/security_labels.py - gajim/common/modules/user_nickname.py - gajim/common/modules/user_tune.py - gajim/common/types.py - gajim/gtk/filetransfer.py - pyrightconfig.json
Changes:
===================================== gajim/common/events.py ===================================== @@ -24,6 +24,7 @@ from dataclasses import field
from nbxmpp.protocol import JID +from nbxmpp.modules.security_labels import Catalog from nbxmpp.structs import HTTPAuthData from nbxmpp.structs import ModerationData from nbxmpp.structs import LocationData @@ -606,7 +607,7 @@ class SecCatalogReceived(ApplicationEvent): name: str = field(init=False, default='sec-catalog-received') account: str jid: str - catalog: dict[str, Any] + catalog: dict[str, Catalog]
@dataclass
===================================== gajim/common/modules/annotations.py ===================================== @@ -14,8 +14,6 @@
# XEP-0145: Annotations
-from typing import Any -from typing import Dict from typing import Union from typing import Optional
@@ -23,6 +21,7 @@ from nbxmpp.errors import MalformedStanzaError from nbxmpp.structs import AnnotationNote from nbxmpp.protocol import JID +from nbxmpp.task import Task
from gajim.common.types import ConnectionT from gajim.common.modules.base import BaseModule @@ -39,13 +38,13 @@ class Annotations(BaseModule): def __init__(self, con: ConnectionT) -> None: BaseModule.__init__(self, con)
- self._annotations: Dict[Union[JID, str], AnnotationNote] = {} + self._annotations: dict[Union[JID, str], AnnotationNote] = {}
def request_annotations(self) -> None: self._nbxmpp('Annotations').request_annotations( callback=self._annotations_received)
- def _annotations_received(self, task: Any) -> None: + def _annotations_received(self, task: Task) -> None: try: annotations = task.finish() except (StanzaError, MalformedStanzaError) as error:
===================================== gajim/common/modules/blocking.py ===================================== @@ -14,13 +14,21 @@
# XEP-0191: Blocking Command
+from __future__ import annotations + +from typing import Generator + import nbxmpp -from nbxmpp.protocol import JID from nbxmpp.namespaces import Namespace +from nbxmpp.protocol import Iq +from nbxmpp.protocol import JID +from nbxmpp.structs import BlockingProperties +from nbxmpp.structs import DiscoInfo from nbxmpp.structs import StanzaHandler from nbxmpp.modules.util import raise_if_error
from gajim.common import app +from gajim.common import types from gajim.common.events import FeatureDiscovered from gajim.common.modules.base import BaseModule from gajim.common.modules.util import as_task @@ -35,10 +43,10 @@ class Blocking(BaseModule): 'request_blocking_list', ]
- def __init__(self, con): + def __init__(self, con: types.Client) -> None: BaseModule.__init__(self, con)
- self.blocked = set() + self.blocked: set[JID] = set()
self.handlers = [ StanzaHandler(name='iq', @@ -49,7 +57,7 @@ def __init__(self, con):
self.supported = False
- def pass_disco(self, info): + def pass_disco(self, info: DiscoInfo) -> None: if Namespace.BLOCKING not in info.features: return
@@ -60,11 +68,11 @@ def pass_disco(self, info):
self._log.info('Discovered blocking: %s', info.jid)
- def is_blocked(self, jid): + def is_blocked(self, jid: JID) -> bool: return jid in self.blocked
@as_task - def get_blocking_list(self): + def get_blocking_list(self) -> Generator[set[JID], None, None]: _task = yield
blocking_list = yield self._nbxmpp('Blocking').request_blocking_list() @@ -78,7 +86,10 @@ def get_blocking_list(self): yield blocking_list
@as_task - def update_blocking_list(self, block, unblock): + def update_blocking_list(self, + block: set[JID], + unblock: set[JID] + ) -> Generator[bool, None, None]: _task = yield
if block: @@ -91,7 +102,11 @@ def update_blocking_list(self, block, unblock):
yield True
- def _blocking_push_received(self, _con, _stanza, properties): + def _blocking_push_received(self, + _con: types.xmppClient, + _stanza: Iq, + properties: BlockingProperties + ) -> None: if not properties.is_blocking: return
@@ -114,13 +129,15 @@ def _blocking_push_received(self, _con, _stanza, properties):
raise nbxmpp.NodeProcessed
- def _unblock_jids(self, jids): + def _unblock_jids(self, jids: set[JID]) -> None: for contact in self._get_contacts_from_jids(jids): contact.set_unblocked() self._presence_probe(contact.jid) self._log.info('Unblock Push: %s', contact.jid)
- def _get_contacts_from_jids(self, jids): + def _get_contacts_from_jids(self, + jids: set[JID] + ) -> Generator[types.BareContactT, None, None]: for jid in jids: if jid.resource is not None: # Currently not supported by GUI
===================================== gajim/common/modules/bookmarks.py ===================================== @@ -14,10 +14,9 @@
# XEP-0048: Bookmarks
+from __future__ import annotations + from typing import Any -from typing import List -from typing import Set -from typing import Tuple from typing import Union from typing import Optional from typing import cast @@ -27,22 +26,24 @@ from nbxmpp.namespaces import Namespace from nbxmpp.protocol import JID from nbxmpp.structs import BookmarkData +from nbxmpp.structs import DiscoInfo +from nbxmpp.structs import MessageProperties from nbxmpp.task import Task + from gi.repository import GLib
from gajim.common import app +from gajim.common import types from gajim.common.events import BookmarksReceived -from gajim.common.types import BookmarksDict from gajim.common.modules.base import BaseModule from gajim.common.modules.contacts import GroupchatContact from gajim.common.modules.util import event_node
- NODE_MAX_NS = 'http://jabber.org/protocol/pubsub#config-node-max'
class Bookmarks(BaseModule): - def __init__(self, con): + def __init__(self, con: types.Client) -> None: BaseModule.__init__(self, con) self._register_pubsub_handler(self._bookmark_event_received) self._register_pubsub_handler(self._bookmark_1_event_received) @@ -50,8 +51,8 @@ def __init__(self, con): self._compat = False self._compat_pep = False self._node_max = False - self._bookmarks: BookmarksDict = {} - self._join_timeouts: List[int] = [] + self._bookmarks: types.BookmarksDict = {} + self._join_timeouts: list[int] = [] self._request_in_progress = True
@property @@ -67,7 +68,7 @@ def compat_pep(self) -> bool: return self._compat_pep
@property - def bookmarks(self) -> List[BookmarkData]: + def bookmarks(self) -> list[BookmarkData]: return list(self._bookmarks.values())
@property @@ -79,7 +80,11 @@ def nativ_bookmarks_used(self) -> bool: return self._bookmark_module() == 'NativeBookmarks'
@event_node(Namespace.BOOKMARKS) - def _bookmark_event_received(self, _con, _stanza, properties): + def _bookmark_event_received(self, + _con: types.xmppClient, + _stanza: Any, + properties: MessageProperties + ) -> None: if properties.pubsub_event.retracted: return
@@ -104,7 +109,11 @@ def _bookmark_event_received(self, _con, _stanza, properties): BookmarksReceived(account=self._account))
@event_node(Namespace.BOOKMARKS_1) - def _bookmark_1_event_received(self, _con, _stanza, properties): + def _bookmark_1_event_received(self, + _con: types.xmppClient, + _stanza: Any, + properties: MessageProperties + ) -> None: if not properties.is_self_message: self._log.warning('%s has an open access bookmarks node', properties.jid) @@ -138,14 +147,14 @@ def _bookmark_1_event_received(self, _con, _stanza, properties): app.ged.raise_event( BookmarksReceived(account=self._account))
- def pass_disco(self, info): + def pass_disco(self, info: DiscoInfo) -> None: self._node_max = NODE_MAX_NS in info.features self._compat_pep = Namespace.BOOKMARKS_COMPAT_PEP in info.features self._compat = Namespace.BOOKMARKS_COMPAT in info.features self._conversion = Namespace.BOOKMARK_CONVERSION in info.features
@functools.lru_cache(maxsize=1) - def _bookmark_module(self): + def _bookmark_module(self) -> str: if not self._con.get_module('PubSub').publish_options: return 'PrivateBookmarks'
@@ -160,7 +169,8 @@ def _bookmark_module(self): return 'PrivateBookmarks'
def _act_on_changed_bookmarks(self, - current_bookmarks: BookmarksDict) -> None: + current_bookmarks: types.BookmarksDict + ) -> None: new_bookmarks = self._convert_to_set(self._bookmarks) old_bookmarks = self._convert_to_set(current_bookmarks) changed = new_bookmarks - old_bookmarks @@ -168,7 +178,7 @@ def _act_on_changed_bookmarks(self, return
join = [jid for jid, autojoin in changed if autojoin] - bookmarks: List[BookmarkData] = [] + bookmarks: list[BookmarkData] = [] for jid in join: self._log.info('Schedule autojoin in 10s for: %s', jid) bookmarks.append(cast(BookmarkData, self._bookmarks.get(jid))) @@ -183,16 +193,17 @@ def _act_on_changed_bookmarks(self, # leave = [jid for jid, autojoin in changed if not autojoin]
@staticmethod - def _convert_to_set(bookmarks: BookmarksDict) -> Set[Tuple[JID, bool]]: - set_: Set[Tuple[JID, bool]] = set() + def _convert_to_set(bookmarks: types.BookmarksDict + ) -> set[tuple[JID, bool]]: + set_: set[tuple[JID, bool]] = set() for jid, bookmark in bookmarks.items(): set_.add((jid, bookmark.autojoin)) return set_
@staticmethod - def _convert_to_dict( - bookmarks: Optional[List[BookmarkData]]) -> BookmarksDict: - _dict: BookmarksDict = {} + def _convert_to_dict(bookmarks: Optional[list[BookmarkData]] + ) -> types.BookmarksDict: + _dict: types.BookmarksDict = {} if not bookmarks: return _dict
@@ -213,7 +224,7 @@ def request_bookmarks(self) -> None:
def _bookmarks_received(self, task: Task) -> None: try: - bookmarks: List[BookmarkData] = task.finish() + bookmarks: list[BookmarkData] = task.finish() except Exception as error: self._log.warning(error) bookmarks = [] @@ -237,7 +248,7 @@ def _cleanup_bookmarks(self, bookmarks: list[BookmarkData]) -> None: 'a groupchat: %s', bookmark.jid) bookmarks.remove(bookmark)
- def store_bookmarks(self, bookmarks: List[BookmarkData]) -> None: + def store_bookmarks(self, bookmarks: list[BookmarkData]) -> None: if not app.account_is_available(self._account): return
@@ -249,11 +260,11 @@ def store_bookmarks(self, bookmarks: List[BookmarkData]) -> None: app.ged.raise_event( BookmarksReceived(account=self._account))
- def _join_with_timeout(self, bookmarks: List[BookmarkData]) -> None: + def _join_with_timeout(self, bookmarks: list[BookmarkData]) -> None: self._join_timeouts.pop(0) self.auto_join_bookmarks(bookmarks)
- def auto_join_bookmarks(self, bookmarks: List[BookmarkData]) -> None: + def auto_join_bookmarks(self, bookmarks: list[BookmarkData]) -> None: for bookmark in bookmarks: if bookmark.autojoin: self._log.info('Autojoin Bookmark: %s', bookmark.jid) @@ -304,9 +315,9 @@ def get_name_from_bookmark(self, jid: Union[str, JID]) -> Optional[str]: def is_bookmark(self, jid: Union[str, JID]) -> bool: return jid in self._bookmarks
- def _remove_timeouts(self): + def _remove_timeouts(self) -> None: for _id in self._join_timeouts: GLib.source_remove(_id)
- def cleanup(self): + def cleanup(self) -> None: self._remove_timeouts()
===================================== gajim/common/modules/carbons.py ===================================== @@ -14,19 +14,23 @@
# XEP-0280: Message Carbons
+from __future__ import annotations + import nbxmpp from nbxmpp.namespaces import Namespace +from nbxmpp.structs import DiscoInfo
+from gajim.common import types from gajim.common.modules.base import BaseModule
class Carbons(BaseModule): - def __init__(self, con): + def __init__(self, con: types.Client) -> None: BaseModule.__init__(self, con)
self.supported = False
- def pass_disco(self, info): + def pass_disco(self, info: DiscoInfo) -> None: if Namespace.CARBONS not in info.features: return
===================================== gajim/common/modules/chatstates.py ===================================== @@ -14,33 +14,36 @@
# XEP-0085: Chat State Notifications
+from __future__ import annotations + from typing import Any -from typing import Dict # pylint: disable=unused-import -from typing import List # pylint: disable=unused-import from typing import Optional
import time from functools import wraps
-import nbxmpp from nbxmpp.namespaces import Namespace +from nbxmpp.protocol import JID +from nbxmpp.protocol import Presence +from nbxmpp.structs import MessageProperties +from nbxmpp.structs import PresenceProperties from nbxmpp.structs import StanzaHandler from nbxmpp.const import Chatstate as State + from gi.repository import GLib
+from gajim.common import types +from gajim.common.const import ClientState from gajim.common.structs import OutgoingMessage from gajim.common.modules.base import BaseModule
-from gajim.common.types import ConnectionT - - INACTIVE_AFTER = 60 PAUSED_AFTER = 10
-def ensure_enabled(func): +def ensure_enabled(func: Any) -> Any: @wraps(func) - def func_wrapper(self, *args, **kwargs): + def func_wrapper(self: Any, *args: Any, **kwargs: Any): # pylint: disable=protected-access if not self._enabled: return None @@ -49,7 +52,7 @@ def func_wrapper(self, *args, **kwargs):
class Chatstate(BaseModule): - def __init__(self, con: ConnectionT) -> None: + def __init__(self, con: types.Client) -> None: BaseModule.__init__(self, con)
self.handlers = [ @@ -62,31 +65,38 @@ def __init__(self, con: ConnectionT) -> None: ]
# Our current chatstate with a specific contact - self._chatstates = {} # type: Dict[str, State] + self._chatstates: dict[JID, State] = {}
# The current chatstate we received from a contact - self._remote_chatstate = {} + self._remote_chatstate: dict[JID, State] = {}
- self._last_keyboard_activity = {} # type: Dict[str, float] - self._last_mouse_activity = {} # type: Dict[str, float] + self._last_keyboard_activity: dict[JID, float] = {} + self._last_mouse_activity: dict[JID, float] = {} self._timeout_id = None - self._delay_timeout_ids = {} # type: Dict[str, str] - self._blocked = [] # type: List[str] + self._delay_timeout_ids: dict[JID, int] = {} + self._blocked: list[JID] = [] self._enabled = False
self._con.connect_signal('state-changed', self._on_client_state_changed) self._con.connect_signal('resume-failed', self._on_client_resume_failed)
- def _on_client_resume_failed(self, _client, _signal_name): + def _on_client_resume_failed(self, + _client: types.Client, + _signal_name: str + ) -> None: self._set_enabled(False)
- def _on_client_state_changed(self, _client, _signal_name, state): + def _on_client_state_changed(self, + _client: types.Client, + _signal_name: str, + state: ClientState + ) -> None: if state.is_disconnected: self._set_enabled(False) elif state.is_connected: self._set_enabled(True)
- def _set_enabled(self, value): + def _set_enabled(self, value: bool) -> None: if self._enabled == value: return
@@ -103,10 +113,10 @@ def _set_enabled(self, value):
@ensure_enabled def _presence_received(self, - _con: ConnectionT, - _stanza: nbxmpp.Presence, - properties: Any) -> None: - + _con: types.xmppClient, + _stanza: Presence, + properties: PresenceProperties + ) -> None: if not properties.type.is_unavailable and not properties.type.is_error: return
@@ -115,6 +125,7 @@ def _presence_received(self,
jid = properties.jid
+ assert jid is not None self._remote_chatstate.pop(jid, None) self._chatstates.pop(jid, None) self._last_mouse_activity.pop(jid, None) @@ -128,7 +139,11 @@ def _presence_received(self,
contact.notify('chatstate-update')
- def _process_chatstate(self, _con, _stanza, properties): + def _process_chatstate(self, + _con: types.xmppClient, + _stanza: Any, + properties: MessageProperties + ) -> None: if properties.type.is_error: return
@@ -141,6 +156,7 @@ def _process_chatstate(self, _con, _stanza, properties): properties.is_carbon_message and properties.carbon.is_sent): return
+ assert properties.jid is not None self._remote_chatstate[properties.jid] = properties.chatstate
self._log.info('Recv: %-10s - %s', properties.chatstate, properties.jid) @@ -152,7 +168,7 @@ def _process_chatstate(self, _con, _stanza, properties): contact.notify('chatstate-update')
@ensure_enabled - def _check_last_interaction(self) -> GLib.SOURCE_CONTINUE: + def _check_last_interaction(self) -> bool: now = time.time() for jid in list(self._last_mouse_activity.keys()): time_ = self._last_mouse_activity[jid] @@ -181,17 +197,19 @@ def _check_last_interaction(self) -> GLib.SOURCE_CONTINUE:
return GLib.SOURCE_CONTINUE
- def get_remote_chatstate(self, jid): + def get_remote_chatstate(self, jid: JID) -> Chatstate: return self._remote_chatstate.get(jid)
@ensure_enabled - def set_active(self, contact) -> None: + def set_active(self, contact: types.ChatContactT) -> None: if contact.settings.get('send_chatstate') == 'disabled': return self._last_mouse_activity[contact.jid] = time.time() self._chatstates[contact.jid] = State.ACTIVE
- def get_active_chatstate(self, contact) -> Optional[str]: + def get_active_chatstate(self, + contact: types.ChatContactT + ) -> Optional[str]: # determines if we add 'active' on outgoing messages if contact.settings.get('send_chatstate') == 'disabled': return None @@ -208,7 +226,10 @@ def get_active_chatstate(self, contact) -> Optional[str]: return 'active'
@ensure_enabled - def block_chatstates(self, contact, block: bool) -> None: + def block_chatstates(self, + contact: types.ChatContactT, + block: bool + ) -> None: # Block sending chatstates to a contact # Used for example if we cycle through the MUC nick list, which # produces a lot of buffer 'changed' signals from the input textview. @@ -219,7 +240,10 @@ def block_chatstates(self, contact, block: bool) -> None: self._blocked.remove(contact.jid)
@ensure_enabled - def set_chatstate_delayed(self, contact, state: State) -> None: + def set_chatstate_delayed(self, + contact: types.ChatContactT, + state: State + ) -> None: # Used when we go from Composing -> Active after deleting all text # from the Textview. We delay the Active state because maybe the # User starts writing again. @@ -228,7 +252,7 @@ def set_chatstate_delayed(self, contact, state: State) -> None: 2, self.set_chatstate, contact, state)
@ensure_enabled - def set_chatstate(self, contact, state: State) -> None: + def set_chatstate(self, contact: types.ChatContactT, state: State) -> None: # Don’t send chatstates to ourself if self._con.get_own_jid().bare_match(contact.jid): return @@ -287,7 +311,10 @@ def set_chatstate(self, contact, state: State) -> None:
self._chatstates[contact.jid] = state
- def _send_chatstate(self, contact, chatstate): + def _send_chatstate(self, + contact: types.ChatContactT, + chatstate: State + ) -> None: type_ = 'groupchat' if contact.is_groupchat else 'chat' message = OutgoingMessage(account=self._account, contact=contact, @@ -299,7 +326,10 @@ def _send_chatstate(self, contact, chatstate): self._con.send_message(message)
@ensure_enabled - def set_mouse_activity(self, contact, was_paused: bool) -> None: + def set_mouse_activity(self, + contact: types.ChatContactT, + was_paused: bool + ) -> None: if contact.settings.get('send_chatstate') == 'disabled': return self._last_mouse_activity[contact.jid] = time.time() @@ -310,21 +340,21 @@ def set_mouse_activity(self, contact, was_paused: bool) -> None: self.set_chatstate(contact, State.ACTIVE)
@ensure_enabled - def set_keyboard_activity(self, contact) -> None: + def set_keyboard_activity(self, contact: types.ChatContactT) -> None: self._last_keyboard_activity[contact.jid] = time.time()
- def remove_delay_timeout(self, contact): + def remove_delay_timeout(self, contact: types.ChatContactT) -> None: timeout = self._delay_timeout_ids.get(contact.jid) if timeout is not None: GLib.source_remove(timeout) del self._delay_timeout_ids[contact.jid]
- def remove_all_delay_timeouts(self): + def remove_all_delay_timeouts(self) -> None: for timeout in self._delay_timeout_ids.values(): GLib.source_remove(timeout) self._delay_timeout_ids.clear()
- def cleanup(self): + def cleanup(self) -> None: self.remove_all_delay_timeouts() if self._timeout_id is not None: GLib.source_remove(self._timeout_id)
===================================== gajim/common/modules/delimiter.py ===================================== @@ -14,9 +14,14 @@
# XEP-0083: Nested Roster Groups
+from __future__ import annotations + +from typing import Generator +from typing import Optional
from nbxmpp.errors import is_error
+from gajim.common import types from gajim.common.modules.base import BaseModule from gajim.common.modules.util import as_task
@@ -29,13 +34,13 @@ class Delimiter(BaseModule): 'set_delimiter' ]
- def __init__(self, con): + def __init__(self, con: types.Client) -> None: BaseModule.__init__(self, con) self.available = False self.delimiter = '::'
@as_task - def get_roster_delimiter(self): + def get_roster_delimiter(self) -> Generator[Optional[str], None, None]: _task = yield
delimiter = yield self.request_delimiter()
===================================== gajim/common/modules/entity_time.py ===================================== @@ -14,7 +14,12 @@
# XEP-0202: Entity Time
+from __future__ import annotations + +from nbxmpp.protocol import JID + from gajim.common import app +from gajim.common import types from gajim.common.modules.base import BaseModule
@@ -27,12 +32,12 @@ class EntityTime(BaseModule): 'disable', ]
- def __init__(self, con): + def __init__(self, con: types.Client) -> None: BaseModule.__init__(self, con)
self.handlers = []
- def set_enabled(self, enabled): + def set_enabled(self, enabled: bool) -> None: if not enabled: self._nbxmpp('EntityTime').disable() return @@ -44,7 +49,7 @@ def set_enabled(self, enabled): self._nbxmpp('EntityTime').enable() self._nbxmpp('EntityTime').set_allow_reply_func(self._allow_reply)
- def _allow_reply(self, jid): + def _allow_reply(self, jid: JID) -> bool: item = self._con.get_module('Roster').get_item(jid.bare) if item is None: return False
===================================== gajim/common/modules/httpupload.py ===================================== @@ -14,21 +14,33 @@
# XEP-0363: HTTP File Upload
+from __future__ import annotations + +from typing import cast +from typing import Callable +from typing import Optional
import os import io from urllib.parse import urlparse import mimetypes
-from nbxmpp.namespaces import Namespace from nbxmpp.errors import StanzaError from nbxmpp.errors import MalformedStanzaError from nbxmpp.errors import HTTPUploadStanzaError +from nbxmpp.namespaces import Namespace +from nbxmpp.protocol import JID +from nbxmpp.structs import DiscoInfo +from nbxmpp.structs import HTTPUploadData +from nbxmpp.task import Task from nbxmpp.util import convert_tls_error_flags + +from gi.repository import Gio from gi.repository import GLib from gi.repository import Soup
from gajim.common import app +from gajim.common import types from gajim.common.i18n import _ from gajim.common.helpers import get_tls_error_phrase from gajim.common.helpers import get_account_proxy @@ -42,21 +54,21 @@ class HTTPUpload(BaseModule):
_nbxmpp_extends = 'HTTPUpload'
- def __init__(self, con): + def __init__(self, con: types.Client) -> None: BaseModule.__init__(self, con)
self.available = False - self.component = None - self.httpupload_namespace = None - self.max_file_size = None # maximum file size in bytes + self.component: Optional[JID] = None + self.httpupload_namespace: Optional[str] = None + self.max_file_size: Optional[float] = None # max file size in bytes
- self._proxy_resolver = None - self._queued_messages = {} + self._proxy_resolver: Optional[Gio.SimpleProxyResolver] = None + self._queued_messages: dict[int, Soup.Message] = {} self._session = Soup.Session() self._session.props.ssl_strict = False - self._session.props.user_agent = 'Gajim %s' % app.version + self._session.props.user_agent = f'Gajim {app.version}'
- def _set_proxy_if_available(self): + def _set_proxy_if_available(self) -> None: proxy = get_account_proxy(self._account) if proxy is None: self._proxy_resolver = None @@ -65,7 +77,7 @@ def _set_proxy_if_available(self): self._proxy_resolver = proxy.get_resolver() self._session.props.proxy_resolver = self._proxy_resolver
- def pass_disco(self, info): + def pass_disco(self, info: DiscoInfo) -> None: if not info.has_httpupload: return
@@ -79,18 +91,24 @@ def pass_disco(self, info): if self.max_file_size is None: self._log.warning('Component does not provide maximum file size') else: - size = GLib.format_size_full(self.max_file_size, + size = GLib.format_size_full(int(self.max_file_size), GLib.FormatSizeFlags.IEC_UNITS) self._log.info('Component has a maximum file size of: %s', size)
for ctrl in app.window.get_controls(account=self._account): ctrl.update_actions()
- def make_transfer(self, path, encryption, contact, groupchat=False): + def make_transfer(self, + path: str, + encryption: Optional[str], + contact: types.ContactT, + groupchat: bool = False + ) -> HTTPFileTransfer: if not path or not os.path.exists(path): raise FileError(_('Could not access file'))
invalid_file = False + msg = '' stat = os.stat(path)
if os.path.isfile(path): @@ -101,10 +119,10 @@ def make_transfer(self, path, encryption, contact, groupchat=False): invalid_file = True msg = _('File does not exist')
- if self.max_file_size is not None and \ - stat.st_size > self.max_file_size: + if (self.max_file_size is not None and + stat.st_size > self.max_file_size): invalid_file = True - size = GLib.format_size_full(self.max_file_size, + size = GLib.format_size_full(int(self.max_file_size), GLib.FormatSizeFlags.IEC_UNITS) msg = _('File is too large, ' 'maximum allowed file size is: %s') % size @@ -124,7 +142,7 @@ def make_transfer(self, path, encryption, contact, groupchat=False): encryption, groupchat)
- def cancel_transfer(self, transfer): + def cancel_transfer(self, transfer: HTTPFileTransfer) -> None: transfer.set_cancelled() message = self._queued_messages.get(id(transfer)) if message is None: @@ -132,7 +150,7 @@ def cancel_transfer(self, transfer):
self._session.cancel_message(message, Soup.Status.CANCELLED)
- def start_transfer(self, transfer): + def start_transfer(self, transfer: HTTPFileTransfer) -> None: if transfer.encryption is not None and not transfer.is_encrypted: transfer.set_encrypting() plugin = app.plugin_manager.encryption_plugins[transfer.encryption] @@ -155,8 +173,8 @@ def start_transfer(self, transfer): callback=self._received_slot, user_data=transfer)
- def _received_slot(self, task): - transfer = task.get_user_data() + def _received_slot(self, task: Task) -> None: + transfer = cast(HTTPFileTransfer, task.get_user_data())
try: result = task.finish() @@ -190,9 +208,10 @@ def _received_slot(self, task):
self._upload_file(transfer)
- def _upload_file(self, transfer): + def _upload_file(self, transfer: HTTPFileTransfer) -> None: transfer.set_started()
+ assert transfer.put_uri is not None message = Soup.Message.new('PUT', transfer.put_uri) message.connect('starting', self._check_certificate, transfer)
@@ -201,8 +220,10 @@ def _upload_file(self, transfer): message.set_flags(Soup.MessageFlags.CAN_REBUILD | Soup.MessageFlags.NO_REDIRECT)
+ assert message.props.request_body is not None message.props.request_body.set_accumulate(False)
+ assert message.props.request_headers is not None message.props.request_headers.set_content_type(transfer.mime, None) message.props.request_headers.set_content_length(transfer.size) for name, value in transfer.headers.items(): @@ -215,7 +236,10 @@ def _upload_file(self, transfer): self._set_proxy_if_available() self._session.queue_message(message, self._on_finish, transfer)
- def _check_certificate(self, message, transfer): + def _check_certificate(self, + message: Soup.Message, + transfer: HTTPFileTransfer + ) -> None: https_used, tls_certificate, tls_errors = message.get_https_status() if not https_used: self._log.warning('HTTPS was not used for upload') @@ -234,7 +258,11 @@ def _check_certificate(self, message, transfer): transfer.set_error('tls-verification-failed', phrase) self._session.cancel_message(message, Soup.Status.CANCELLED)
- def _on_finish(self, _session, message, transfer): + def _on_finish(self, + _session: Soup.Session, + message: Soup.Message, + transfer: HTTPFileTransfer + ) -> None: self._queued_messages.pop(id(transfer), None)
if message.props.status_code == Soup.Status.CANCELLED: @@ -252,25 +280,36 @@ def _on_finish(self, _session, message, transfer): phrase) transfer.set_error('http-response', phrase)
- def _on_wrote_chunk(self, message, transfer): + def _on_wrote_chunk(self, + message: Soup.Message, + transfer: HTTPFileTransfer + ) -> None: transfer.update_progress() if transfer.is_complete: + assert message.props.request_body is not None message.props.request_body.complete() return
bytes_ = transfer.get_chunk() + assert bytes_ is not None self._session.pause_message(message) GLib.idle_add(self._append, message, bytes_)
- def _append(self, message, bytes_): + def _append(self, message: Soup.Message, bytes_: bytes) -> None: if message.props.status_code == Soup.Status.CANCELLED: return self._session.unpause_message(message) + assert message.props.request_body is not None message.props.request_body.append(bytes_)
@staticmethod - def _on_wrote_headers(message, transfer): - message.props.request_body.append(transfer.get_chunk()) + def _on_wrote_headers(message: Soup.Message, + transfer: HTTPFileTransfer + ) -> None: + bytes_ = transfer.get_chunk() + assert bytes_ is not None + assert message.props.request_body is not None + message.props.request_body.append(bytes_)
class HTTPFileTransfer(FileTransfer): @@ -288,12 +327,13 @@ class HTTPFileTransfer(FileTransfer): }
def __init__(self, - account, - path, - contact, - mime, - encryption, - groupchat): + account: str, + path: str, + contact: types.ContactT, + mime: str, + encryption: Optional[str], + groupchat: bool + ) -> None:
FileTransfer.__init__(self, account)
@@ -304,76 +344,76 @@ def __init__(self, self._mime = mime
self.size = os.stat(path).st_size - self.put_uri = None - self.get_uri = None - self._uri_transform_func = None + self.put_uri: Optional[str] = None + self.get_uri: Optional[str] = None + self._uri_transform_func: Optional[Callable[[str], str]] = None
self._stream = None - self._data = None - self._headers = {} + self._data: Optional[bytes] = None + self._headers: dict[str, str] = {}
self._is_encrypted = False
@property - def mime(self): + def mime(self) -> str: return self._mime
@property - def contact(self): + def contact(self) -> types.ContactT: return self._contact
@property - def is_groupchat(self): + def is_groupchat(self) -> bool: return self._groupchat
@property - def encryption(self): + def encryption(self) -> Optional[str]: return self._encryption
@property - def headers(self): + def headers(self) -> dict[str, str]: return self._headers
@property - def path(self): + def path(self) -> str: return self._path
@property - def is_encrypted(self): + def is_encrypted(self) -> bool: return self._is_encrypted
- def get_transformed_uri(self): + def get_transformed_uri(self) -> str: if self._uri_transform_func is not None: return self._uri_transform_func(self.get_uri) return self.get_uri
- def set_uri_transform_func(self, func): + def set_uri_transform_func(self, func: Callable[[str], str]) -> None: self._uri_transform_func = func
@property def filename(self) -> str: return os.path.basename(self._path)
- def set_error(self, domain, text=''): + def set_error(self, domain: str, text: str = '') -> None: if not text: text = self._errors[domain]
self._close() super().set_error(domain, text)
- def set_finished(self): + def set_finished(self) -> None: self._close() super().set_finished()
- def set_encrypted_data(self, data): + def set_encrypted_data(self, data: bytes) -> None: self._data = data self._is_encrypted = True
- def _close(self): + def _close(self) -> None: if self._stream is not None: self._stream.close()
- def get_chunk(self): + def get_chunk(self) -> Optional[bytes]: if self._stream is None: if self._encryption is None: self._stream = open(self._path, 'rb') # pylint: disable=consider-using-with @@ -389,12 +429,12 @@ def get_chunk(self): self._close() return data
- def get_data(self): + def get_data(self) -> bytes: with open(self._path, 'rb') as file: data = file.read() return data
- def process_result(self, result): + def process_result(self, result: HTTPUploadData) -> None: self.put_uri = result.put_uri self.get_uri = result.get_uri self._headers = result.headers
===================================== gajim/common/modules/jingle.py ===================================== @@ -28,16 +28,22 @@ # * config: # - codecs
+from __future__ import annotations + +from typing import Any from typing import Optional
import logging
import nbxmpp from nbxmpp.namespaces import Namespace +from nbxmpp.protocol import Iq from nbxmpp.structs import StanzaHandler +from nbxmpp.structs import IqProperties
from gajim.common import helpers from gajim.common import jingle_xtls +from gajim.common import types from gajim.common.file_props import FileProp from gajim.common.modules.base import BaseModule from gajim.common.jingle_session import JingleSession @@ -51,7 +57,7 @@
class Jingle(BaseModule): - def __init__(self, con): + def __init__(self, con: types.Client) -> None: BaseModule.__init__(self, con)
self.handlers = [ @@ -80,8 +86,8 @@ def __init__(self, con):
# dictionary: (jid, iq stanza id) => JingleSession object, # one time callbacks - self.__iq_responses = {} - self.files = [] + self.__iq_responses: dict[tuple[str, str], JingleSession] = {} + self.files: list[dict[str, Any]] = []
def delete_jingle_session(self, sid: str) -> None: """ @@ -94,19 +100,31 @@ def delete_jingle_session(self, sid: str) -> None: self._sessions[sid].callbacks = [] del self._sessions[sid]
- def _on_pubkey_request(self, con, stanza, _properties): + def _on_pubkey_request(self, + con: types.xmppClient, + stanza: Iq, + _properties: IqProperties + ) -> None: jid_from = helpers.get_full_jid_from_iq(stanza) self._log.info('Pubkey request from %s', jid_from) sid = stanza.getAttr('id') jingle_xtls.send_cert(con, jid_from, sid) raise nbxmpp.NodeProcessed
- def _pubkey_result_received(self, con, stanza, _properties): + def _pubkey_result_received(self, + con: types.xmppClient, + stanza: Iq, + _properties: IqProperties + ) -> None: jid_from = helpers.get_full_jid_from_iq(stanza) self._log.info('Pubkey result from %s', jid_from) jingle_xtls.handle_new_cert(con, stanza, jid_from)
- def _on_jingle_iq(self, _con, stanza, _properties): + def _on_jingle_iq(self, + _con: types.xmppClient, + stanza: Iq, + _properties: IqProperties + ) -> None: """ The jingle stanza dispatcher
@@ -138,6 +156,7 @@ def _on_jingle_iq(self, _con, stanza, _properties): if id_ in sesn.iq_ids: sesn.on_stanza(stanza) return + # do we need to create a new jingle object if sid not in self._sessions: #TODO: tie-breaking and other things... @@ -148,14 +167,15 @@ def _on_jingle_iq(self, _con, stanza, _properties): self._sessions[sid].collect_iq_id(id_) self._sessions[sid].on_stanza(stanza) # Delete invalid/unneeded sessions - if sid in self._sessions and \ - self._sessions[sid].state == JingleStates.ENDED: + if (sid in self._sessions and + self._sessions[sid].state == JingleStates.ENDED): self.delete_jingle_session(sid) raise nbxmpp.NodeProcessed
def start_audio(self, jid: str) -> str: - if self.get_jingle_session(jid, media='audio'): - return self.get_jingle_session(jid, media='audio').sid + audio_session = self.get_jingle_session(jid, media='audio') + if audio_session is not None: + return audio_session.sid jingle = self.get_jingle_session(jid, media='video') if jingle: jingle.add_content('voice', JingleAudio(jingle)) @@ -167,8 +187,9 @@ def start_audio(self, jid: str) -> str: return jingle.sid
def start_video(self, jid: str) -> str: - if self.get_jingle_session(jid, media='video'): - return self.get_jingle_session(jid, media='video').sid + video_session = self.get_jingle_session(jid, media='video') + if video_session is not None: + return video_session.sid jingle = self.get_jingle_session(jid, media='audio') if jingle: video = JingleVideo(jingle) @@ -249,7 +270,7 @@ def start_file_transfer(self, return transfer.transport.sid
@staticmethod - def __hash_support(contact): + def __hash_support(contact: types.ResourceContact) -> Optional[str]: if contact.supports(Namespace.HASHES_2): if contact.supports(Namespace.HASHES_BLAKE2B_512): return 'blake2b-512' @@ -265,7 +286,11 @@ def __hash_support(contact): return 'sha-256' return None
- def get_jingle_sessions(self, jid, sid=None, media=None): + def get_jingle_sessions(self, + jid: Optional[str], + sid: Optional[str] = None, + media: Optional[str] = None + ) -> list[JingleSession]: if sid: return [se for se in self._sessions.values() if se.sid == sid]
@@ -276,12 +301,17 @@ def get_jingle_sessions(self, jid, sid=None, media=None): return [se for se in sessions if se.get_content(media)] return sessions
- def set_file_info(self, file_): + def set_file_info(self, file_: dict[str, Any]) -> None: # Saves information about the files we have transferred # in case they need to be requested again. self.files.append(file_)
- def get_file_info(self, peerjid, hash_=None, name=None, _account=None): + def get_file_info(self, + peerjid: str, + hash_: Optional[str] = None, + name: Optional[str] = None, + _account: Optional[str] = None + ) -> Optional[dict[str, Any]]: if hash_: for file in self.files: # DEBUG #if f['hash'] == '1294809248109223':
===================================== gajim/common/modules/last_activity.py ===================================== @@ -14,8 +14,15 @@
# XEP-0012: Last Activity
+from __future__ import annotations + +from typing import cast + +from nbxmpp.protocol import JID + from gajim.common import app from gajim.common import idle +from gajim.common import types from gajim.common.modules.base import BaseModule
@@ -28,10 +35,10 @@ class LastActivity(BaseModule): 'disable', ]
- def __init__(self, con): + def __init__(self, con: types.Client) -> None: BaseModule.__init__(self, con)
- def set_enabled(self, enabled): + def set_enabled(self, enabled: bool) -> None: if not enabled or not app.is_installed('IDLE'): self._nbxmpp('LastActivity').disable() return @@ -43,10 +50,11 @@ def set_enabled(self, enabled): self._nbxmpp('LastActivity').set_idle_func(idle.Monitor.get_idle_sec) self._nbxmpp('LastActivity').set_allow_reply_func(self._allow_reply)
- def _allow_reply(self, jid): + def _allow_reply(self, jid: JID) -> bool: item = self._con.get_module('Roster').get_item(jid.bare) if item is None: return False
- contact = self._get_contact(jid.bare) + contact = cast(types.BareContact, self._get_contact( + JID.from_string(jid.bare))) return contact.is_subscribed
===================================== gajim/common/modules/misc.py ===================================== @@ -14,19 +14,25 @@
# All XEPs that don’t need their own module
+from typing import Optional + import logging
+from nbxmpp.structs import MessageProperties + +from gajim.common.helpers import AdditionalDataDict from gajim.common.i18n import get_rfc5646_lang
log = logging.getLogger('gajim.c.m.misc')
- # XEP-0066: Out of Band Data - -def parse_oob(properties, additional_data): +def parse_oob(properties: MessageProperties, + additional_data: AdditionalDataDict + ) -> None: if not properties.is_oob: return
+ assert properties.oob is not None additional_data.set_value('gajim', 'oob_url', properties.oob.url) if properties.oob.desc is not None: additional_data.set_value('gajim', 'oob_desc', @@ -34,18 +40,20 @@ def parse_oob(properties, additional_data):
# XEP-0308: Last Message Correction - -def parse_correction(properties): +def parse_correction(properties: MessageProperties) -> Optional[str]: if not properties.is_correction: return None + assert properties.correction is not None return properties.correction.id
# XEP-0071: XHTML-IM - -def parse_xhtml(properties, additional_data): +def parse_xhtml(properties: MessageProperties, + additional_data: AdditionalDataDict + ) -> None: if not properties.has_xhtml: return
+ assert properties.xhtml is not None body = properties.xhtml.get_body(get_rfc5646_lang()) additional_data.set_value('gajim', 'xhtml', body)
===================================== gajim/common/modules/receipts.py ===================================== @@ -14,18 +14,24 @@
# XEP-0184: Message Delivery Receipts
+from __future__ import annotations + import nbxmpp from nbxmpp.structs import StanzaHandler from nbxmpp.namespaces import Namespace from nbxmpp.modules.receipts import build_receipt +from nbxmpp.protocol import JID +from nbxmpp.protocol import Message +from nbxmpp.structs import MessageProperties
from gajim.common import app +from gajim.common import types from gajim.common.events import ReceiptReceived from gajim.common.modules.base import BaseModule
class Receipts(BaseModule): - def __init__(self, con): + def __init__(self, con: types.Client) -> None: BaseModule.__init__(self, con)
self.handlers = [ @@ -35,10 +41,15 @@ def __init__(self, con): priority=46), ]
- def _process_message_receipt(self, _con, stanza, properties): + def _process_message_receipt(self, + _con: types.xmppClient, + stanza: Message, + properties: MessageProperties + ) -> None: if not properties.is_receipt: return
+ assert properties.receipt is not None if properties.type.is_error: if properties.receipt.is_request: return @@ -94,9 +105,9 @@ def _process_message_receipt(self, _con, stanza, properties):
raise nbxmpp.NodeProcessed
- def _should_answer(self, properties): + def _should_answer(self, properties: MessageProperties) -> bool: if properties.is_muc_pm: return True
- contact = self._get_contact(properties.jid.bare) + contact = self._get_contact(JID.from_string(properties.jid.bare)) return contact.is_subscribed
===================================== gajim/common/modules/register.py ===================================== @@ -14,9 +14,12 @@
# XEP-0077: In-Band Registration
+from __future__ import annotations
from nbxmpp.namespaces import Namespace +from nbxmpp.structs import DiscoInfo
+from gajim.common import types from gajim.common.modules.base import BaseModule
@@ -31,10 +34,10 @@ class Register(BaseModule): 'submit_register_form', ]
- def __init__(self, con): + def __init__(self, con: types.Client): BaseModule.__init__(self, con)
self.supported = False
- def pass_disco(self, info): + def pass_disco(self, info: DiscoInfo) -> None: self.supported = Namespace.REGISTER in info.features
===================================== gajim/common/modules/roster.py ===================================== @@ -23,14 +23,16 @@
import nbxmpp from nbxmpp.namespaces import Namespace +from nbxmpp.protocol import Iq from nbxmpp.protocol import JID +from nbxmpp.structs import IqProperties from nbxmpp.structs import RosterData from nbxmpp.structs import RosterItem from nbxmpp.structs import StanzaHandler from nbxmpp.task import Task
from gajim.common import app -from gajim.common.client import Client +from gajim.common import types from gajim.common.events import RosterReceived from gajim.common.events import RosterPush from gajim.common.modules.base import BaseModule @@ -45,7 +47,7 @@ class Roster(BaseModule): 'set_item', ]
- def __init__(self, client: Client) -> None: + def __init__(self, client: types.Client) -> None: BaseModule.__init__(self, client)
self.handlers = [ @@ -131,9 +133,14 @@ def _set_roster_from_data(self, items: list[RosterItem]) -> None:
self._store_roster()
- def _process_roster_push(self, _con, _stanza, properties): + def _process_roster_push(self, + _con: types.xmppClient, + _stanza: Iq, + properties: IqProperties + ) -> None: self._log.info('Push received')
+ assert properties.roster is not None item = properties.roster.item if item.subscription == 'remove': self._roster.pop(item.jid)
===================================== gajim/common/modules/roster_item_exchange.py ===================================== @@ -14,19 +14,25 @@
# XEP-0144: Roster Item Exchange
+from __future__ import annotations + import nbxmpp from nbxmpp.namespaces import Namespace +from nbxmpp.protocol import Iq +from nbxmpp.protocol import JID +from nbxmpp.structs import IqProperties from nbxmpp.structs import StanzaHandler
from gajim.common import app from gajim.common import helpers +from gajim.common import types from gajim.common.events import RosterItemExchangeEvent from gajim.common.i18n import _ from gajim.common.modules.base import BaseModule
class RosterItemExchange(BaseModule): - def __init__(self, con): + def __init__(self, con: types.Client) -> None: BaseModule.__init__(self, con)
self.handlers = [ @@ -39,7 +45,11 @@ def __init__(self, con): ns=Namespace.ROSTERX), ]
- def received_item(self, _con, stanza, properties): + def received_item(self, + _con: types.xmppClient, + stanza: Iq, + properties: IqProperties + ) -> None: # stanza can be a message or a iq
self._log.info('Received roster items from %s', stanza.getFrom()) @@ -62,7 +72,7 @@ def received_item(self, _con, stanza, properties): item.getAttr('jid')) continue name = item.getAttr('name') - contact = self._get_contact(jid) + contact = self._get_contact(JID.from_string(jid)) groups = [] same_groups = True for group in item.getTags('group'): @@ -94,18 +104,23 @@ def received_item(self, _con, stanza, properties):
raise nbxmpp.NodeProcessed
- def send_contacts(self, contacts, fjid, type_='message'): + def send_contacts(self, + contacts: list[types.ChatContactT], + fjid: str, + type_: str = 'message' + ) -> None: if not app.account_is_available(self._account): return
if type_ == 'message': if len(contacts) == 1: msg = _('Sent contact: "%(jid)s" (%(name)s)') % { - 'jid': contacts[0].jid, 'name': contacts[0].name} + 'jid': contacts[0].jid, + 'name': contacts[0].name} else: msg = _('Sent contacts:') for contact in contacts: - msg += '\n "%s" (%s)' % (contact.jid, contact.name) + msg += f'\n "{contact.jid}" ({contact.name})' stanza = nbxmpp.Message(to=app.get_jid_without_resource(fjid), body=msg) elif type_ == 'iq':
===================================== gajim/common/modules/security_labels.py ===================================== @@ -14,13 +14,18 @@
# XEP-0258: Security Labels in XMPP
+from __future__ import annotations + +from typing import Generator from typing import Optional
from nbxmpp.errors import is_error from nbxmpp.namespaces import Namespace from nbxmpp.modules.security_labels import Catalog +from nbxmpp.structs import DiscoInfo
from gajim.common import app +from gajim.common import types from gajim.common.events import SecCatalogReceived from gajim.common.modules.base import BaseModule from gajim.common.modules.util import as_task @@ -33,13 +38,13 @@ class SecLabels(BaseModule): 'request_catalog', ]
- def __init__(self, con): + def __init__(self, con: types.Client) -> None: BaseModule.__init__(self, con)
self._catalogs: dict[str, Catalog] = {} self.supported = False
- def pass_disco(self, info): + def pass_disco(self, info: DiscoInfo) -> None: if Namespace.SECLABEL not in info.features: return
@@ -47,7 +52,7 @@ def pass_disco(self, info): self._log.info('Discovered security labels: %s', info.jid)
@as_task - def request_catalog(self, jid: str): + def request_catalog(self, jid: str) -> Generator[Catalog, None, None]:
_task = yield
===================================== gajim/common/modules/user_nickname.py ===================================== @@ -14,9 +14,15 @@
# XEP-0172: User Nickname
+from __future__ import annotations + +from typing import Any + from nbxmpp.namespaces import Namespace +from nbxmpp.structs import MessageProperties
from gajim.common import app +from gajim.common import types from gajim.common.modules.base import BaseModule from gajim.common.modules.util import event_node
@@ -29,12 +35,16 @@ class UserNickname(BaseModule): 'set_access_model', ]
- def __init__(self, con): + def __init__(self, con: types.Client): BaseModule.__init__(self, con) self._register_pubsub_handler(self._nickname_received)
@event_node(Namespace.NICK) - def _nickname_received(self, _con, _stanza, properties): + def _nickname_received(self, + _con: types.xmppClient, + _stanza: Any, + properties: MessageProperties + ) -> None: if properties.pubsub_event.retracted: return
===================================== gajim/common/modules/user_tune.py ===================================== @@ -16,18 +16,23 @@
from __future__ import annotations
+from typing import Any from typing import Optional
from nbxmpp.namespaces import Namespace from nbxmpp.protocol import JID +from nbxmpp.structs import MessageProperties from nbxmpp.structs import TuneData
from gajim.common import app from gajim.common import ged +from gajim.common import types from gajim.common.modules.base import BaseModule from gajim.common.modules.util import event_node from gajim.common.modules.util import store_publish from gajim.common.dbus.music_track import MusicTrackListener +from gajim.common.events import MusicTrackChanged +from gajim.common.events import SignedIn from gajim.common.helpers import event_filter
@@ -38,7 +43,7 @@ class UserTune(BaseModule): 'set_tune', ]
- def __init__(self, con): + def __init__(self, con: types.Client) -> None: BaseModule.__init__(self, con) self._register_pubsub_handler(self._tune_received) self._current_tune: Optional[TuneData] = None @@ -51,7 +56,11 @@ def get_contact_tune(self, jid: JID) -> Optional[TuneData]: return self._contact_tunes.get(jid)
@event_node(Namespace.TUNE) - def _tune_received(self, _con, _stanza, properties): + def _tune_received(self, + _con: types.xmppClient, + _stanza: Any, + properties: MessageProperties + ) -> None: if properties.pubsub_event.retracted: return
@@ -65,7 +74,7 @@ def _tune_received(self, _con, _stanza, properties): contact.notify('tune-update', data)
@store_publish - def set_tune(self, tune, force=False): + def set_tune(self, tune: Optional[TuneData], force: bool = False) -> None: if not self._con.get_module('PEP').supported: return
@@ -81,7 +90,7 @@ def set_tune(self, tune, force=False): self._log.info('Send %s', tune) self._nbxmpp('Tune').set_tune(tune)
- def set_enabled(self, enable): + def set_enabled(self, enable: bool) -> None: if enable: self.register_events([ ('music-track-changed', ged.CORE, self._on_music_track_changed), @@ -96,10 +105,10 @@ def _publish_current_tune(self): self.set_tune(MusicTrackListener.get().current_tune)
@event_filter(['account']) - def _on_signed_in(self, _event): + def _on_signed_in(self, _event: SignedIn) -> None: self._publish_current_tune()
- def _on_music_track_changed(self, event): + def _on_music_track_changed(self, event: MusicTrackChanged) -> None: if self._current_tune == event.info: return
===================================== gajim/common/types.py ===================================== @@ -78,6 +78,7 @@ AnyCallableT = Callable[..., Any] ObservableCbDict = dict[str, list[weakref.WeakMethod[AnyCallableT]]]
+BareContactT = Union['BareContact'] ChatContactT = Union['BareContact', 'GroupchatContact', 'GroupchatParticipant'] OneOnOneContactT = Union['BareContact', 'GroupchatParticipant'] GroupchatContactT = Union['GroupchatContact']
===================================== gajim/gtk/filetransfer.py ===================================== @@ -371,7 +371,7 @@ def _on_yes(): new_file_props.hash_ = file_props.hash_ new_file_props.type_ = 'r' tsid = client.get_module('Jingle').start_file_transfer( - jid, new_file_props, True) + str(jid), new_file_props, True)
new_file_props.transport_sid = tsid self.add_transfer(account, contact, new_file_props)
===================================== pyrightconfig.json ===================================== @@ -30,6 +30,7 @@ "gajim/common/idle.py", "gajim/common/logging_helpers.py", "gajim/common/modules/chat_markers.py", + "gajim/common/modules/register.py", "gajim/common/passwords.py", "gajim/common/regex.py", "gajim/common/setting_values.py",
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/compare/51ecba65121fb3aa5291a374f127a120...