Commit c9e219c1 authored by mathieui's avatar mathieui

mypy: Reduce errors on muctab.py by a lot

parent 4fae01c0
...@@ -15,7 +15,17 @@ import shutil ...@@ -15,7 +15,17 @@ import shutil
import time import time
import uuid import uuid
from collections import defaultdict from collections import defaultdict
from typing import Callable, Dict, List, Optional, Set, Tuple, Type from typing import (
cast,
Callable,
Dict,
List,
Optional,
Set,
Tuple,
Type,
TypeVar,
)
from xml.etree import ElementTree as ET from xml.etree import ElementTree as ET
from functools import partial from functools import partial
...@@ -65,6 +75,7 @@ from poezio.ui.types import Message, InfoMessage ...@@ -65,6 +75,7 @@ from poezio.ui.types import Message, InfoMessage
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
T = TypeVar('T', bound=tabs.Tab)
class Core: class Core:
""" """
...@@ -99,8 +110,10 @@ class Core: ...@@ -99,8 +110,10 @@ class Core:
# that are displayed in almost all tabs, in an # that are displayed in almost all tabs, in an
# information window. # information window.
self.information_buffer = TextBuffer() self.information_buffer = TextBuffer()
self.information_win_size = config.get( self.information_win_size = cast(
'info_win_height', section='var') int,
config.get('info_win_height', section='var'),
)
self.information_win = windows.TextWin(300) self.information_win = windows.TextWin(300)
self.information_buffer.add_window(self.information_win) self.information_buffer.add_window(self.information_win)
self.left_tab_win = None self.left_tab_win = None
...@@ -813,7 +826,7 @@ class Core: ...@@ -813,7 +826,7 @@ class Core:
####################### XMPP-related actions ################################## ####################### XMPP-related actions ##################################
def get_status(self) -> str: def get_status(self) -> Status:
""" """
Get the last status that was previously set Get the last status that was previously set
""" """
...@@ -1016,7 +1029,7 @@ class Core: ...@@ -1016,7 +1029,7 @@ class Core:
### Tab getters ### ### Tab getters ###
def get_tabs(self, cls: Type[tabs.Tab] = None) -> List[tabs.Tab]: def get_tabs(self, cls: Type[T] = None) -> List[T]:
"Get all the tabs of a type" "Get all the tabs of a type"
if cls is None: if cls is None:
return self.tabs.get_tabs() return self.tabs.get_tabs()
...@@ -1324,7 +1337,7 @@ class Core: ...@@ -1324,7 +1337,7 @@ class Core:
if tab.name.startswith(room_name): if tab.name.startswith(room_name):
tab.activate(reason=reason) tab.activate(reason=reason)
def on_user_changed_status_in_private(self, jid: JID, status: str) -> None: def on_user_changed_status_in_private(self, jid: JID, status: Status) -> None:
tab = self.tabs.by_name_and_class(jid, tabs.ChatTab) tab = self.tabs.by_name_and_class(jid, tabs.ChatTab)
if tab is not None: # display the message in private if tab is not None: # display the message in private
tab.update_status(status) tab.update_status(status)
...@@ -1652,7 +1665,7 @@ class Core: ...@@ -1652,7 +1665,7 @@ class Core:
return return
else: else:
scr = self.stdscr scr = self.stdscr
tabs.Tab.resize(scr) tabs.Tab.initial_resize(scr)
self.resize_global_info_bar() self.resize_global_info_bar()
self.resize_global_information_win() self.resize_global_information_win()
for tab in self.tabs: for tab in self.tabs:
...@@ -2105,7 +2118,7 @@ class Core: ...@@ -2105,7 +2118,7 @@ class Core:
self.bookmarks.get_remote(self.xmpp, self.information, self.bookmarks.get_remote(self.xmpp, self.information,
_join_remote_only) _join_remote_only)
def room_error(self, error, room_name): def room_error(self, error: IqError, room_name: str) -> None:
""" """
Display the error in the tab Display the error in the tab
""" """
......
""" """
Module defining structures useful to the core class and related methods Module defining structures useful to the core class and related methods
""" """
from dataclasses import dataclass
from typing import Any, Callable, List, Dict
__all__ = [ __all__ = [
'ERROR_AND_STATUS_CODES', 'DEPRECATED_ERRORS', 'POSSIBLE_SHOW', 'Status', 'ERROR_AND_STATUS_CODES', 'DEPRECATED_ERRORS', 'POSSIBLE_SHOW', 'Status',
...@@ -51,23 +53,11 @@ POSSIBLE_SHOW = { ...@@ -51,23 +53,11 @@ POSSIBLE_SHOW = {
} }
@dataclass
class Status: class Status:
__slots__ = ('show', 'message') __slots__ = ('show', 'message')
show: str
def __init__(self, show, message): message: str
self.show = show
self.message = message
class Command:
__slots__ = ('func', 'desc', 'comp', 'short_desc', 'usage')
def __init__(self, func, desc, comp, short_desc, usage):
self.func = func
self.desc = desc
self.comp = comp
self.short_desc = short_desc
self.usage = usage
class Completion: class Completion:
...@@ -75,8 +65,13 @@ class Completion: ...@@ -75,8 +65,13 @@ class Completion:
A completion result essentially currying the input completion call. A completion result essentially currying the input completion call.
""" """
__slots__ = ['func', 'args', 'kwargs', 'comp_list'] __slots__ = ['func', 'args', 'kwargs', 'comp_list']
def __init__(
def __init__(self, func, comp_list, *args, **kwargs): self,
func: Callable[..., Any],
comp_list: List[str],
*args: Any,
**kwargs: Any
) -> None:
self.func = func self.func = func
self.comp_list = comp_list self.comp_list = comp_list
self.args = args self.args = args
...@@ -84,3 +79,12 @@ class Completion: ...@@ -84,3 +79,12 @@ class Completion:
def run(self): def run(self):
return self.func(self.comp_list, *self.args, **self.kwargs) return self.func(self.comp_list, *self.args, **self.kwargs)
@dataclass
class Command:
__slots__ = ('func', 'desc', 'comp', 'short_desc', 'usage')
func: Callable[..., Any]
desc: str
comp: Callable[['windows.Input'], Completion]
short_desc: str
usage: str
...@@ -347,16 +347,16 @@ class Tabs: ...@@ -347,16 +347,16 @@ class Tabs:
if new_pos < len(self._tabs): if new_pos < len(self._tabs):
old_tab = self._tabs[old_pos] old_tab = self._tabs[old_pos]
self._tabs[new_pos], self._tabs[ self._tabs[new_pos], self._tabs[
old_pos] = old_tab, tabs.GapTab(self) old_pos] = old_tab, tabs.GapTab(None)
else: else:
self._tabs.append(self._tabs[old_pos]) self._tabs.append(self._tabs[old_pos])
self._tabs[old_pos] = tabs.GapTab(self) self._tabs[old_pos] = tabs.GapTab(None)
else: else:
if new_pos > old_pos: if new_pos > old_pos:
self._tabs.insert(new_pos, tab) self._tabs.insert(new_pos, tab)
self._tabs[old_pos] = tabs.GapTab(self) self._tabs[old_pos] = tabs.GapTab(None)
elif new_pos < old_pos: elif new_pos < old_pos:
self._tabs[old_pos] = tabs.GapTab(self) self._tabs[old_pos] = tabs.GapTab(None)
self._tabs.insert(new_pos, tab) self._tabs.insert(new_pos, tab)
else: else:
return False return False
......
...@@ -5,7 +5,8 @@ upstream. ...@@ -5,7 +5,8 @@ upstream.
TODO: Check that they are fixed and remove those hacks TODO: Check that they are fixed and remove those hacks
""" """
from slixmpp.stanza import Message from typing import Callable, Any
from slixmpp import Message, Iq, ClientXMPP
from slixmpp.xmlstream import ET from slixmpp.xmlstream import ET
import logging import logging
...@@ -25,7 +26,7 @@ def has_identity(xmpp, jid, identity, on_true=None, on_false=None): ...@@ -25,7 +26,7 @@ def has_identity(xmpp, jid, identity, on_true=None, on_false=None):
xmpp.plugin['xep_0030'].get_info(jid=jid, callback=_cb) xmpp.plugin['xep_0030'].get_info(jid=jid, callback=_cb)
def get_room_form(xmpp, room, callback): def get_room_form(xmpp: ClientXMPP, room: str, callback: Callable[[Iq], Any]):
def _cb(result): def _cb(result):
if result["type"] == "error": if result["type"] == "error":
return callback(None) return callback(None)
......
...@@ -104,7 +104,7 @@ def main(): ...@@ -104,7 +104,7 @@ def main():
logger.create_logger() logger.create_logger()
from poezio import roster from poezio import roster
roster.create_roster() roster.roster.reset()
from poezio.core.core import Core from poezio.core.core import Core
......
...@@ -10,6 +10,8 @@ Defines the Roster and RosterGroup classes ...@@ -10,6 +10,8 @@ Defines the Roster and RosterGroup classes
import logging import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
from typing import List
from poezio.config import config from poezio.config import config
from poezio.contact import Contact from poezio.contact import Contact
from poezio.roster_sorting import SORTING_METHODS, GROUP_SORTING_METHODS from poezio.roster_sorting import SORTING_METHODS, GROUP_SORTING_METHODS
...@@ -18,6 +20,7 @@ from os import path as p ...@@ -18,6 +20,7 @@ from os import path as p
from datetime import datetime from datetime import datetime
from poezio.common import safeJID from poezio.common import safeJID
from slixmpp.exceptions import IqError, IqTimeout from slixmpp.exceptions import IqError, IqTimeout
from slixmpp import JID
class Roster: class Roster:
...@@ -29,6 +32,22 @@ class Roster: ...@@ -29,6 +32,22 @@ class Roster:
DEFAULT_FILTER = (lambda x, y: None, None) DEFAULT_FILTER = (lambda x, y: None, None)
def __init__(self): def __init__(self):
self.__node = None
# A tuple(function, *args) function to filter contacts
# on search, for example
self.contact_filter = self.DEFAULT_FILTER
self.groups = {}
self.contacts = {}
self.length = 0
self.connected = 0
self.folded_groups = []
# Used for caching roster infos
self.last_built = datetime.now()
self.last_modified = datetime.now()
def reset(self):
""" """
node: the RosterSingle from slixmpp node: the RosterSingle from slixmpp
""" """
...@@ -143,7 +162,7 @@ class Roster: ...@@ -143,7 +162,7 @@ class Roster:
"""Subscribe to a jid""" """Subscribe to a jid"""
self.__node.subscribe(jid) self.__node.subscribe(jid)
def jids(self): def jids(self) -> List[JID]:
"""List of the contact JIDS""" """List of the contact JIDS"""
l = [] l = []
for key in self.__node.keys(): for key in self.__node.keys():
...@@ -335,11 +354,6 @@ class RosterGroup: ...@@ -335,11 +354,6 @@ class RosterGroup:
return len([1 for contact in self.contacts if len(contact)]) return len([1 for contact in self.contacts if len(contact)])
def create_roster():
"Create the global roster object"
global roster
roster = Roster()
# Shared roster object # Shared roster object
roster = None roster = Roster()
...@@ -28,6 +28,7 @@ from typing import ( ...@@ -28,6 +28,7 @@ from typing import (
List, List,
Optional, Optional,
Union, Union,
Tuple,
TYPE_CHECKING, TYPE_CHECKING,
) )
...@@ -52,6 +53,8 @@ from slixmpp import JID, InvalidJID, Message as SMessage ...@@ -52,6 +53,8 @@ from slixmpp import JID, InvalidJID, Message as SMessage
if TYPE_CHECKING: if TYPE_CHECKING:
from _curses import _CursesWindow # pylint: disable=E0611 from _curses import _CursesWindow # pylint: disable=E0611
from poezio.size_manager import SizeManager
from poezio.core.core import Core
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -117,7 +120,7 @@ class Tab: ...@@ -117,7 +120,7 @@ class Tab:
height = 1 height = 1
width = 1 width = 1
def __init__(self, core): def __init__(self, core: 'Core'):
self.core = core self.core = core
self.nb = 0 self.nb = 0
if not hasattr(self, 'name'): if not hasattr(self, 'name'):
...@@ -133,7 +136,7 @@ class Tab: ...@@ -133,7 +136,7 @@ class Tab:
self.commands = {} # and their own commands self.commands = {} # and their own commands
@property @property
def size(self) -> int: def size(self) -> 'SizeManager':
return self.core.size return self.core.size
@staticmethod @staticmethod
...@@ -196,7 +199,7 @@ class Tab: ...@@ -196,7 +199,7 @@ class Tab:
self._state = 'normal' self._state = 'normal'
@staticmethod @staticmethod
def resize(scr: '_CursesWindow'): def initial_resize(scr: '_CursesWindow'):
Tab.height, Tab.width = scr.getmaxyx() Tab.height, Tab.width = scr.getmaxyx()
windows.base_wins.TAB_WIN = scr windows.base_wins.TAB_WIN = scr
...@@ -327,7 +330,7 @@ class Tab: ...@@ -327,7 +330,7 @@ class Tab:
else: else:
return False return False
def refresh_tab_win(self): def refresh_tab_win(self) -> None:
if config.get('enable_vertical_tab_list'): if config.get('enable_vertical_tab_list'):
left_tab_win = self.core.left_tab_win left_tab_win = self.core.left_tab_win
if left_tab_win and not self.size.core_degrade_x: if left_tab_win and not self.size.core_degrade_x:
...@@ -371,12 +374,12 @@ class Tab: ...@@ -371,12 +374,12 @@ class Tab:
""" """
pass pass
def update_commands(self): def update_commands(self) -> None:
for c in self.plugin_commands: for c in self.plugin_commands:
if c not in self.commands: if c not in self.commands:
self.commands[c] = self.plugin_commands[c] self.commands[c] = self.plugin_commands[c]
def update_keys(self): def update_keys(self) -> None:
for k in self.plugin_keys: for k in self.plugin_keys:
if k not in self.key_func: if k not in self.key_func:
self.key_func[k] = self.plugin_keys[k] self.key_func[k] = self.plugin_keys[k]
...@@ -435,7 +438,7 @@ class Tab: ...@@ -435,7 +438,7 @@ class Tab:
""" """
pass pass
def on_close(self): def on_close(self) -> None:
""" """
Called when the tab is to be closed Called when the tab is to be closed
""" """
...@@ -443,7 +446,7 @@ class Tab: ...@@ -443,7 +446,7 @@ class Tab:
self.input.on_delete() self.input.on_delete()
self.closed = True self.closed = True
def matching_names(self) -> List[str]: def matching_names(self) -> List[Tuple[int, str]]:
""" """
Returns a list of strings that are used to name a tab with the /win Returns a list of strings that are used to name a tab with the /win
command. For example you could switch to a tab that returns command. For example you could switch to a tab that returns
...@@ -532,7 +535,7 @@ class ChatTab(Tab): ...@@ -532,7 +535,7 @@ class ChatTab(Tab):
desc='Fix the last message with whatever you want.', desc='Fix the last message with whatever you want.',
shortdesc='Correct the last message.', shortdesc='Correct the last message.',
completion=self.completion_correct) completion=self.completion_correct)
self.chat_state = None self.chat_state = None # type: Optional[str]
self.update_commands() self.update_commands()
self.update_keys() self.update_keys()
...@@ -667,11 +670,11 @@ class ChatTab(Tab): ...@@ -667,11 +670,11 @@ class ChatTab(Tab):
self._text_buffer.messages = [] self._text_buffer.messages = []
self.text_win.rebuild_everything(self._text_buffer) self.text_win.rebuild_everything(self._text_buffer)
def check_send_chat_state(self): def check_send_chat_state(self) -> bool:
"If we should send a chat state" "If we should send a chat state"
return True return True
def send_chat_state(self, state, always_send=False): def send_chat_state(self, state: str, always_send: bool = False) -> None:
""" """
Send an empty chatstate message Send an empty chatstate message
""" """
...@@ -691,9 +694,8 @@ class ChatTab(Tab): ...@@ -691,9 +694,8 @@ class ChatTab(Tab):
x = ET.Element('{%s}x' % NS_MUC_USER) x = ET.Element('{%s}x' % NS_MUC_USER)
msg.append(x) msg.append(x)
msg.send() msg.send()
return True
def send_composing_chat_state(self, empty_after): def send_composing_chat_state(self, empty_after: bool) -> None:
""" """
Send the "active" or "composing" chatstate, depending Send the "active" or "composing" chatstate, depending
on the the current status of the input on the the current status of the input
...@@ -729,7 +731,7 @@ class ChatTab(Tab): ...@@ -729,7 +731,7 @@ class ChatTab(Tab):
self.core.add_timed_event(new_event) self.core.add_timed_event(new_event)
self.timed_event_not_paused = new_event self.timed_event_not_paused = new_event
def cancel_paused_delay(self): def cancel_paused_delay(self) -> None:
""" """
Remove that event from the list and set it to None. Remove that event from the list and set it to None.
Called for example when the input is emptied, or when the message Called for example when the input is emptied, or when the message
...@@ -741,7 +743,7 @@ class ChatTab(Tab): ...@@ -741,7 +743,7 @@ class ChatTab(Tab):
self.core.remove_timed_event(self.timed_event_not_paused) self.core.remove_timed_event(self.timed_event_not_paused)
self.timed_event_not_paused = None self.timed_event_not_paused = None
def set_last_sent_message(self, msg, correct=False): def set_last_sent_message(self, msg: SMessage, correct: bool = False) -> None:
"""Ensure last_sent_message is set with the correct attributes""" """Ensure last_sent_message is set with the correct attributes"""
if correct: if correct:
# XXX: Is the copy needed. Is the object passed here reused # XXX: Is the copy needed. Is the object passed here reused
...@@ -751,7 +753,7 @@ class ChatTab(Tab): ...@@ -751,7 +753,7 @@ class ChatTab(Tab):
self.last_sent_message = msg self.last_sent_message = msg
@command_args_parser.raw @command_args_parser.raw
def command_correct(self, line): def command_correct(self, line: str) -> None:
""" """
/correct <fixed message> /correct <fixed message>
""" """
...@@ -777,7 +779,7 @@ class ChatTab(Tab): ...@@ -777,7 +779,7 @@ class ChatTab(Tab):
return self.core.status.show in ('xa', 'away') or\ return self.core.status.show in ('xa', 'away') or\
(hasattr(self, 'directed_presence') and not self.directed_presence) (hasattr(self, 'directed_presence') and not self.directed_presence)
def move_separator(self): def move_separator(self) -> None:
self.text_win.remove_line_separator() self.text_win.remove_line_separator()
self.text_win.add_line_separator(self._text_buffer) self.text_win.add_line_separator(self._text_buffer)
self.text_win.refresh() self.text_win.refresh()
...@@ -786,7 +788,7 @@ class ChatTab(Tab): ...@@ -786,7 +788,7 @@ class ChatTab(Tab):
def get_conversation_messages(self): def get_conversation_messages(self):
return self._text_buffer.messages return self._text_buffer.messages
def check_scrolled(self): def check_scrolled(self) -> None:
if self.text_win.pos != 0: if self.text_win.pos != 0:
self.state = 'scrolled' self.state = 'scrolled'
......
This diff is collapsed.
...@@ -145,7 +145,7 @@ class PrivateTab(OneToOneTab): ...@@ -145,7 +145,7 @@ class PrivateTab(OneToOneTab):
@refresh_wrapper.always @refresh_wrapper.always
@command_args_parser.raw @command_args_parser.raw
def command_say(self, line, attention=False, correct=False): def command_say(self, line: str, attention: bool = False, correct: bool = False) -> None:
if not self.on: if not self.on:
return return
our_jid = JID(self.jid.bare) our_jid = JID(self.jid.bare)
......
...@@ -32,6 +32,7 @@ from poezio.ui.types import ( ...@@ -32,6 +32,7 @@ from poezio.ui.types import (
if TYPE_CHECKING: if TYPE_CHECKING:
from poezio.windows.text_win import TextWin from poezio.windows.text_win import TextWin
from poezio.user import User
class CorrectionError(Exception): class CorrectionError(Exception):
...@@ -249,7 +250,7 @@ class TextBuffer: ...@@ -249,7 +250,7 @@ class TextBuffer:
new_id: str, new_id: str,
highlight: bool = False, highlight: bool = False,
time: Optional[datetime] = None, time: Optional[datetime] = None,
user: Optional[str] = None, user: Optional['User'] = None,
jid: Optional[str] = None) -> Message: jid: Optional[str] = None) -> Message:
"""