Philipp Hörist pushed to branch master at gajim / gajim
Commits: d1005551 by lovetox at 2021-12-26T14:47:25+01:00 Tooltips: Add type annotations
- - - - - 1218e6e4 by lovetox at 2021-12-26T14:47:25+01:00 Structs: Add type annotations
- - - - - b95664f4 by lovetox at 2021-12-26T14:47:25+01:00 Contacts: Add type annotations
- - - - - 8a2bccca by lovetox at 2021-12-26T14:47:25+01:00 Controls: Remove unused code
- - - - - 91bbd15f by lovetox at 2021-12-26T14:47:25+01:00 GroupchatRoster: Refactor
- Add type annotations - Refactor code so it works better with typing - Remove unused methods
- - - - - 1710897f by lovetox at 2021-12-26T14:47:25+01:00 Update pylint tests
- Disable checks which we cover with pyright
- - - - -
8 changed files:
- gajim/common/modules/contacts.py - gajim/common/structs.py - gajim/gtk/controls/groupchat.py - gajim/gtk/controls/private.py - gajim/gtk/groupchat_roster.py - gajim/gtk/tooltips.py - pylintrc - scripts/ci/pylint.sh
Changes:
===================================== gajim/common/modules/contacts.py ===================================== @@ -31,6 +31,7 @@ from gajim.common.const import SimpleClientState from gajim.common.structs import UNKNOWN_PRESENCE from gajim.common.structs import UNKNOWN_MUC_PRESENCE +from gajim.common.structs import MUCPresenceData from gajim.common.helpers import Observable from gajim.common.modules.base import BaseModule from gajim.common.helpers import get_groupchat_name @@ -573,10 +574,10 @@ def is_in_roster(self) -> bool: return False
@property - def presence(self): + def presence(self) -> MUCPresenceData: return self._presence
- def set_presence(self, presence): + def set_presence(self, presence: MUCPresenceData) -> None: self._presence = presence
@property @@ -631,7 +632,10 @@ def get_avatar(self, return app.interface.avatar_storage.get_surface( self, size, scale, show, style=style)
- def update_presence(self, presence, *args, notify: bool = True) -> None: + def update_presence(self, + presence: MUCPresenceData, + *args: Any, + notify: bool = True) -> None: if not notify: self._presence = presence return @@ -661,7 +665,7 @@ def update_presence(self, presence, *args, notify: bool = True) -> None: for signal in signals: self.notify(signal, *args)
- def set_state(self, state, presence) -> None: + def set_state(self, state, presence: MUCPresenceData) -> None: self._presence = presence self.notify(state)
===================================== gajim/common/structs.py ===================================== @@ -23,6 +23,7 @@ from nbxmpp.protocol import JID from nbxmpp.const import Role from nbxmpp.const import Affiliation +from nbxmpp.const import PresenceShow
from gajim.common.const import MUCJoinedState from gajim.common.const import KindConstant @@ -207,13 +208,13 @@ def from_presence(cls, properties):
@dataclass(frozen=True) class MUCPresenceData: - show: str + show: PresenceShow status: str - idle_time: str + idle_time: Optional[float] available: bool - affiliation: str - role: str - real_jid: JID + affiliation: Affiliation + role: Role + real_jid: Optional[JID]
@classmethod def from_presence(cls, properties):
===================================== gajim/gtk/controls/groupchat.py ===================================== @@ -703,9 +703,6 @@ def draw_banner_text(self) -> None: """ self.xml.banner_name_label.set_text(self.contact.name)
- def _on_update_gc_avatar(self, event): - self.roster.process_avatar_update(event) - def _on_bookmarks_received(self, _event): self.draw_banner_text()
===================================== gajim/gtk/controls/private.py ===================================== @@ -52,9 +52,6 @@ def __init__(self, account: str, jid: JID) -> None:
ChatControl.__init__(self, account, jid)
- # self.register_events([ - # ('update-gc-avatar', ged.GUI1, self._on_update_gc_avatar), - def _connect_contact_signals(self) -> None: self.contact.multi_connect({ 'user-avatar-update': self._on_user_avatar_update,
===================================== gajim/gtk/groupchat_roster.py ===================================== @@ -13,10 +13,10 @@ # along with Gajim. If not, see http://www.gnu.org/licenses/.
from __future__ import annotations + from typing import Any -from typing import cast from typing import Optional -from typing import Tuple +from typing import cast
import locale from enum import IntEnum @@ -26,7 +26,6 @@ from gi.repository import GLib from gi.repository import GObject from nbxmpp.const import Affiliation -from nbxmpp.const import Role from nbxmpp.structs import MessageProperties
from gajim.common import app @@ -37,6 +36,7 @@ from gajim.common.helpers import jid_is_blocked from gajim.common.const import AvatarSize from gajim.common.const import StyleAttr +from gajim.common.nec import NetworkEvent
from gajim.gui_menu_builder import get_groupchat_roster_menu from .tooltips import GCTooltip @@ -84,9 +84,8 @@ def __init__(self, self.room_jid = room_jid self._control = control self._control_id = control.control_id - self._show_roles = True self._tooltip = GCTooltip() - self._group_chat_contact = control.contact + self._group_chat_contact = cast(types.GroupchatContact, control.contact) self._group_chat_contact.connect( 'user-avatar-update', self._on_user_avatar_update) self._group_chat_contact.connect('user-joined', self._on_user_joined) @@ -99,22 +98,18 @@ def __init__(self, 'user-status-show-changed', self._on_user_status_show_changed) self._group_chat_contact.connect( 'user-nickname-changed', self._on_user_nickname_changed) - # self._group_chat_contact.connect('muc-user-presence-update', - # self._on_muc_user_presence_update)
self._ui = get_builder('groupchat_roster.ui') self._ui.roster_treeview.set_model(None) self.add(self._ui.roster_treeview)
- # Holds the Gtk.TreeRowReference for each contact self._contact_refs: dict[str, Gtk.TreeRowReference] = {} - # Holds the Gtk.TreeRowReference for each group self._group_refs: dict[str, Gtk.TreeRowReference] = {}
- self._store = cast(Gtk.TreeStore, self._ui.participant_store) + self._store = self._ui.participant_store self._store.set_sort_func(Column.TEXT, self._tree_compare_iters)
- self._roster = cast(Gtk.TreeView, self._ui.roster_treeview) + self._roster = self._ui.roster_treeview self._roster.set_search_equal_func(self._search_func) self._roster.set_has_tooltip(True) self._roster.connect('query-tooltip', self._query_tooltip) @@ -135,12 +130,9 @@ def __init__(self, def _on_focus_out(treeview: Gtk.TreeView, _param: Gdk.EventFocus) -> None: treeview.get_selection().unselect_all()
- def set_model(self) -> None: + def _set_model(self) -> None: self._roster.set_model(self._store)
- def set_show_roles(self, enabled: bool) -> None: - self._show_roles = enabled - def _query_tooltip(self, widget: Gtk.Widget, x_pos: int, @@ -148,18 +140,20 @@ def _query_tooltip(self, _keyboard_mode: bool, tooltip: Gtk.Tooltip ) -> bool: - try: - row = self._roster.get_path_at_pos(x_pos, y_pos)[0] - except TypeError: + + row = self._roster.get_path_at_pos(x_pos, y_pos) + if row is None: self._tooltip.clear_tooltip() return False - if not row: + + path, _, _, _ = row + if path is None: self._tooltip.clear_tooltip() return False
iter_ = None try: - iter_ = self._store.get_iter(row) + iter_ = self._store.get_iter(path) except Exception: self._tooltip.clear_tooltip() return False @@ -223,7 +217,7 @@ def _add_contact(self, contact: types.GroupchatParticipant) -> None: role_path = None if not group_iter: group_iter = self._store.append( - None, (None, group_text, None, False, group_name)) + None, [None, group_text, None, False, group_name]) role_path = self._store.get_path(group_iter) group_ref = Gtk.TreeRowReference(self._store, role_path) self._group_refs[group_name] = group_ref @@ -233,12 +227,12 @@ def _add_contact(self, contact: types.GroupchatParticipant) -> None: self.get_scale_factor())
iter_ = self._store.append(group_iter, - (surface, nick, None, True, nick)) + [surface, nick, None, True, nick]) self._contact_refs[nick] = Gtk.TreeRowReference( self._store, self._store.get_path(iter_))
- self.draw_groups() - self.draw_contact(nick) + self._draw_groups() + self._draw_contact(nick)
if (role_path is not None and self._roster.get_model() is not None): @@ -251,7 +245,7 @@ def _on_user_left(self, *args: Any ) -> None: self._remove_contact(user_contact) - self.draw_groups() + self._draw_groups()
def _update_contact(self, _contact: types.GroupchatContact, @@ -279,7 +273,7 @@ def _on_user_status_show_changed(self, user_contact: types.GroupchatParticipant, *args: Any ) -> None: - self.draw_contact(user_contact.name) + self._draw_contact(user_contact.name)
def _remove_contact(self, contact: types.GroupchatParticipant) -> None: nick = contact.name @@ -300,7 +294,7 @@ def _remove_contact(self, contact: types.GroupchatParticipant) -> None:
@staticmethod def _get_group_from_contact(contact: types.GroupchatParticipant - ) -> Tuple[str, str]: + ) -> tuple[str, str]: if contact.affiliation in (Affiliation.OWNER, Affiliation.ADMIN): return contact.affiliation.value, get_uf_affiliation( contact.affiliation, plural=True) @@ -357,6 +351,9 @@ def _on_roster_button_press_event(self, return
path, _, _, _ = pos + if path is None: + return + iter_ = self._store.get_iter(path) if self._store.iter_parent(iter_) is None: # Group row @@ -380,7 +377,7 @@ def _show_contact_menu(self, nick: str) -> None: self_contact, contact)
- def destroy(menu, _pspec): + def destroy(menu: Gtk.Menu, _pspec: GObject.ParamSpec) -> None: visible = menu.get_property('visible') if not visible: GLib.idle_add(menu.destroy) @@ -438,22 +435,22 @@ def invalidate_sort(self) -> None:
def initial_draw(self) -> None: self.enable_sort(True) - self.set_model() + self._set_model() self._roster.expand_all()
- def redraw(self) -> None: + def _redraw(self) -> None: self._roster.set_model(None) self._roster.set_model(self._store) self._roster.expand_all()
- def draw_contact(self, nick: str) -> None: + def _draw_contact(self, nick: str) -> None: iter_ = self._get_contact_iter(nick) if not iter_: return
contact = self._group_chat_contact.get_resource(nick)
- self.draw_avatar(contact) + self._draw_avatar(contact)
self._store[iter_][Column.EVENT] = False
@@ -480,9 +477,13 @@ def draw_contact(self, nick: str) -> None:
def draw_contacts(self) -> None: for nick in self._contact_refs: - self.draw_contact(nick) + self._draw_contact(nick) + + def _draw_groups(self) -> None: + for group in self._group_refs: + self._draw_group(group)
- def draw_group(self, group: str) -> None: + def _draw_group(self, group: str) -> None: group_iter = self._get_group_iter(group) if not group_iter: return @@ -499,11 +500,7 @@ def draw_group(self, group: str) -> None:
self._store[group_iter][Column.TEXT] = group_text
- def draw_groups(self) -> None: - for group in self._group_refs: - self.draw_group(group) - - def draw_avatar(self, contact: types.GroupchatParticipant) -> None: + def _draw_avatar(self, contact: types.GroupchatParticipant) -> None: iter_ = self._get_contact_iter(contact.name) if iter_ is None: return @@ -512,8 +509,11 @@ def draw_avatar(self, contact: types.GroupchatParticipant) -> None: self.get_scale_factor()) self._store[iter_][Column.AVATAR] = surface
- def _on_user_avatar_update(self, _contact, _signal_name, user_contact): - self.draw_avatar(user_contact) + def _on_user_avatar_update(self, + _contact: types.GroupchatContact, + _signal_name: str, + user_contact: types.GroupchatParticipant): + self._draw_avatar(user_contact)
def _get_total_user_count(self) -> int: count = 0 @@ -521,15 +521,8 @@ def _get_total_user_count(self) -> int: count += self._store.iter_n_children(group_row.iter) return count
- def get_role(self, nick: str) -> Role: - contact = self._group_chat_contact.get_resource(nick) - return contact.role - - def _on_theme_update(self, _event): - self.redraw() - - def process_avatar_update(self, event): - self.draw_avatar(event.contact) + def _on_theme_update(self, _event: NetworkEvent) -> None: + self._redraw()
def clear(self) -> None: self._contact_refs = {} @@ -538,16 +531,15 @@ def clear(self) -> None:
def _on_destroy(self, _roster: Any) -> None: self._group_chat_contact.disconnect(self) - self._contact_refs = {} self._group_refs = {} - self._control = None self._roster.set_model(None) - self._roster = None self._store.clear() # Store keeps a ref on the object if we dont unset the sort func self._store.set_sort_func(Column.TEXT, print) - self._store = None self._tooltip.destroy() - self._tooltip = None + del self._roster + del self._store + del self._control + del self._tooltip app.check_finalize(self)
===================================== gajim/gtk/tooltips.py ===================================== @@ -35,7 +35,7 @@
from nbxmpp import JID
-from gajim.common import app +from gajim.common import app, types from gajim.common import helpers from gajim.common.const import AvatarSize from gajim.common.const import PEPEventType @@ -51,15 +51,18 @@
class GCTooltip: - def __init__(self): + def __init__(self) -> None: self._contact = None
self._ui = get_builder('groupchat_roster_tooltip.ui')
- def clear_tooltip(self): + def clear_tooltip(self) -> None: self._contact = None
- def get_tooltip(self, contact): + def get_tooltip(self, + contact: types.GroupchatParticipant + ) -> tuple[bool, Gtk.Grid]: + if self._contact == contact: return True, self._ui.tooltip_grid
@@ -67,14 +70,14 @@ def get_tooltip(self, contact): self._contact = contact return False, self._ui.tooltip_grid
- def _hide_grid_children(self): + def _hide_grid_children(self) -> None: """ Hide all Elements of the Tooltip Grid """ for child in self._ui.tooltip_grid.get_children(): child.hide()
- def _populate_grid(self, contact): + def _populate_grid(self, contact: types.GroupchatParticipant) -> None: """ Populate the Tooltip Grid with data of from the contact """ @@ -119,18 +122,20 @@ def destroy(self):
class RosterTooltip: - def __init__(self): + def __init__(self) -> None: self._row = None self._ui = get_builder('roster_tooltip.ui')
- def clear_tooltip(self): + def clear_tooltip(self) -> None: self._row = None for widget in self._ui.resources_box.get_children(): widget.destroy() for widget in self._ui.tooltip_grid.get_children(): widget.hide()
- def get_tooltip(self, row, contact): + def get_tooltip(self, + row: Gtk.TreePath, + contact: types.BareContact) -> tuple[bool, Gtk.Grid]: if self._row == row: return True, self._ui.tooltip_grid
@@ -138,7 +143,7 @@ def get_tooltip(self, row, contact): self._row = row return False, self._ui.tooltip_grid
- def _populate_grid(self, contact): + def _populate_grid(self, contact: types.BareContact) -> None: self.clear_tooltip() scale = self._ui.tooltip_grid.get_scale_factor()
@@ -184,7 +189,7 @@ def _populate_grid(self, contact): break last_widget.set_vexpand(True)
- def _add_resources(self, contact): + def _add_resources(self, contact: types.BareContact) -> None: for resource in contact.iter_resources(): resource_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
@@ -241,7 +246,7 @@ def _add_resources(self, contact):
self._ui.resources_box.show_all()
- def _append_pep_info(self, contact): + def _append_pep_info(self, contact: types.BareContact) -> None: if PEPEventType.TUNE in contact.pep: tune = format_tune(*contact.pep[PEPEventType.TUNE]) self._ui.tune.set_markup(tune) @@ -256,7 +261,7 @@ def _append_pep_info(self, contact):
class FileTransfersTooltip: - def __init__(self): + def __init__(self) -> None: self.sid = None self.widget = None if app.settings.get('use_kib_mib'): @@ -264,11 +269,11 @@ def __init__(self): else: self.units = GLib.FormatSizeFlags.DEFAULT
- def clear_tooltip(self): + def clear_tooltip(self) -> None: self.sid = None self.widget = None
- def get_tooltip(self, file_props, sid): + def get_tooltip(self, file_props, sid) -> tuple[bool, Gtk.Widget]: if self.sid == sid: return True, self.widget
@@ -276,7 +281,7 @@ def get_tooltip(self, file_props, sid): self.sid = sid return False, self.widget
- def _create_tooltip(self, file_props, _sid): + def _create_tooltip(self, file_props, _sid) -> None: ft_grid = Gtk.Grid.new() ft_grid.insert_column(0) ft_grid.set_row_spacing(6) @@ -336,7 +341,7 @@ def _create_tooltip(self, file_props, _sid): return ft_grid
@staticmethod - def _get_current_status(file_props): + def _get_current_status(file_props) -> None: if file_props.stopped: return Q_('?transfer status:Aborted') if file_props.completed:
===================================== pylintrc ===================================== @@ -50,9 +50,12 @@ confidence= # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" +# +# Most errors here are disabled because they are covered by pyright # C0111 missing-docstring # W0511 fix-me -disable=C0111,W0511 +# +disable=C0111,W0511,E1101,E1102,E1111,E1120,E1121,E1123,E1124,E1125,E1126,E1127,E1128,E1129,E1130,E1131,E1132,E1133,E1134,E1135,E1136,E1137,E1138,E1139,E1140,E1141,E1142,I1101,W0212,W1113,W1114,W1115,W1116
# Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option
===================================== scripts/ci/pylint.sh ===================================== @@ -5,18 +5,54 @@ set -e
PYLINT=${PYLINT:-pylint}
+# Errors which are covered by pyright +# +# E1101 no-member +# E1102 not-callable +# E1111 assignment-from-no-return +# E1120 no-value-for-parameter +# E1121 too-many-function-args +# E1123 unexpected-keyword-arg +# E1124 redundant-keyword-arg +# E1125 missing-kwoa +# E1126 invalid-sequence-index +# E1127 invalid-slice-index +# E1128 assignment-from-none +# E1129 not-context-manager +# E1130 invalid-unary-operand-type +# E1131 unsupported-binary-operation +# E1132 repeated-keyword +# E1133 not-an-iterable +# E1134 not-a-mapping +# E1135 unsupported-membership-test +# E1136 unsubscriptable-object +# E1137 unsupported-assignment-operation +# E1138 unsupported-delete-operation +# E1139 invalid-metaclass +# E1140 unhashable-dict-key +# E1141 dict-iter-missing-items +# E1142 await-outside-async +# I1101 c-extension-no-member +# W0212 protected-access +# W1113 keyword-arg-before-vararg +# W1114 arguments-out-of-order +# W1115 non-str-assignment-to-dunder-name +# W1116 isinstance-second-argument-not-valid-type + +IGNORE_PYRIGHT='E1101,E1102,E1111,E1120,E1121,E1123,E1124,E1125,E1126,E1127,E1128,E1129,E1130,E1131,E1132,E1133,E1134,E1135,E1136,E1137,E1138,E1139,E1140,E1141,E1142,I1101,W0212,W1113,W1114,W1115,W1116' + IGNORE_ALWAYS='R0801,C0209,W0237,W0707,R1732,W1404,W1406,R1725'
-IGNORE_ERRORS=C0103,C0302,C0301,C0330,C0411,C0415,E0401,E0611,E1101,E1133,E1136,R0201,R0901,R0904,R0912,R0913,R0914,R0915,R0916,R1702,R1710,W0201,W0212,W0221,W0223,W0231,W0233,W0603,W0613 +IGNORE_ERRORS=C0103,C0302,C0301,C0330,C0411,C0415,E0401,E0611,R0201,R0901,R0904,R0912,R0913,R0914,R0915,R0916,R1702,R1710,W0201,W0221,W0223,W0231,W0233,W0603,W0613
-IGNORE_GTK_MODULE_ERRORS=C0103,C0301,C0330,C0415,E0401,E0611,E1101,E1133,E1136,R0201,R0904,R0915,R1710,W0201,W0212,W0233,W0221,W0613 +IGNORE_GTK_MODULE_ERRORS=C0103,C0301,C0330,C0415,E0401,E0611,R0201,R0904,R0915,R1710,W0201,W0233,W0221,W0613
"$PYLINT" --version
-"$PYLINT" --disable="$IGNORE_ALWAYS,$IGNORE_ERRORS" --ignore=modules,dbus,gtk "$@" -"$PYLINT" --disable="$IGNORE_ALWAYS,$IGNORE_GTK_MODULE_ERRORS" "$@/gtk" -"$PYLINT" --disable="$IGNORE_ALWAYS,E0401,C0415" "$@/common/modules" -"$PYLINT" --disable=$IGNORE_ALWAYS "$@/common/dbus" +"$PYLINT" --disable="$IGNORE_PYRIGHT,$IGNORE_ALWAYS,$IGNORE_ERRORS" --ignore=modules,dbus,gtk "$@" +"$PYLINT" --disable="$IGNORE_PYRIGHT,$IGNORE_ALWAYS,$IGNORE_GTK_MODULE_ERRORS" "$@/gtk" +"$PYLINT" --disable="$IGNORE_PYRIGHT,$IGNORE_ALWAYS,E0401,C0415" "$@/common/modules" +"$PYLINT" --disable="$IGNORE_PYRIGHT,$IGNORE_ALWAYS" "$@/common/dbus"
# C0103 invalid-name # C0209 use-f-string @@ -26,9 +62,6 @@ IGNORE_GTK_MODULE_ERRORS=C0103,C0301,C0330,C0415,E0401,E0611,E1101,E1133,E1136,R # C0415 import-outside-toplevel # E0401 import-error # E0611 no-name-in-module -# E1101 no-member -# E1133 not-an-iterable -# E1136 unsubscriptable-object # R0201 no-self-use # R0801 duplicat-code # R0901 too-many-ancestors @@ -43,7 +76,6 @@ IGNORE_GTK_MODULE_ERRORS=C0103,C0301,C0330,C0415,E0401,E0611,E1101,E1133,E1136,R # R1732 consider-using-with # R1725 super-with-arguments # W0201 attribute-defined-outside-init -# W0212 protected-access # W0221 arguments-differ # W0223 abstract-method # W0231 super-init-not-called
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/compare/47d66504f3aafaa02e9039f279712a2a...