From 5ea82ac0af1cb855c9333796004c6a97da6b5ad4 Mon Sep 17 00:00:00 2001 From: mathieui Date: Wed, 15 Aug 2018 14:21:59 +0200 Subject: Fix mypy errors, add type annotations --- poezio/bookmarks.py | 2 +- poezio/common.py | 13 +++++++++---- poezio/config.py | 4 ++-- poezio/core/core.py | 10 +++++----- poezio/core/tabs.py | 4 ++-- poezio/keyboard.py | 2 +- poezio/tabs/adhoc_commands_list.py | 9 ++++++--- poezio/tabs/basetabs.py | 9 ++++++--- poezio/tabs/bookmarkstab.py | 12 ++++++++---- poezio/tabs/confirmtab.py | 9 ++++++--- poezio/tabs/conversationtab.py | 22 ++++++++++++---------- poezio/tabs/data_forms.py | 8 ++++++-- poezio/tabs/listtab.py | 13 +++++++------ poezio/tabs/muclisttab.py | 9 ++++++--- poezio/tabs/muctab.py | 12 +++++++----- poezio/tabs/privatetab.py | 14 ++++++++------ poezio/tabs/rostertab.py | 14 +++++++------- poezio/theming.py | 6 +++--- poezio/user.py | 2 +- poezio/windows/inputs.py | 16 +++++++++------- 20 files changed, 112 insertions(+), 78 deletions(-) diff --git a/poezio/bookmarks.py b/poezio/bookmarks.py index 91f862c8..f6f22363 100644 --- a/poezio/bookmarks.py +++ b/poezio/bookmarks.py @@ -47,7 +47,7 @@ class Bookmark: autojoin=False, nick: Optional[str] = None, password: Optional[str] = None, - method='local'): + method='local') -> None: self.jid = jid self.name = name or jid self.autojoin = autojoin diff --git a/poezio/common.py b/poezio/common.py index a021d898..83587b8c 100644 --- a/poezio/common.py +++ b/poezio/common.py @@ -47,7 +47,8 @@ def _is_in_path(command: str, return_abs_path=False) -> Union[bool, str]: and *return_abs_path* is True, otherwise False. """ - for directory in os.getenv('PATH').split(os.pathsep): + path = os.getenv('PATH') or '' + for directory in path.split(os.pathsep): try: if command in os.listdir(directory): if return_abs_path: @@ -114,7 +115,11 @@ def get_os_info() -> str: if os.access(str(path_to_file), os.X_OK): # the file is executable (f.e. CRUX) # yes, then run it and get the first line of output. - text = _get_output_of_command(str(path_to_file))[0] + output = _get_output_of_command(str(path_to_file)) + if output: + text = output[0] + else: + text = '' else: with path_to_file.open(encoding='utf-8') as fdes: text = fdes.readline().strip() # get only first line @@ -224,7 +229,7 @@ def get_local_time(utc_time: datetime) -> datetime: return local_time -def find_delayed_tag(message: Message) -> Tuple[bool, datetime]: +def find_delayed_tag(message: Message) -> Tuple[bool, Optional[datetime]]: """ Check if a message is delayed or not. @@ -235,6 +240,7 @@ def find_delayed_tag(message: Message) -> Tuple[bool, datetime]: find_delay = message.xml.find delay_tag = find_delay('{urn:xmpp:delay}delay') + date = None # type: Optional[datetime] if delay_tag is not None: delayed = True date = _datetime_tuple(delay_tag.attrib['stamp']) @@ -247,7 +253,6 @@ def find_delayed_tag(message: Message) -> Tuple[bool, datetime]: date = _datetime_tuple(delay_tag.attrib['stamp']) else: delayed = False - date = None return (delayed, date) diff --git a/poezio/config.py b/poezio/config.py index 944557a6..8223e5c0 100644 --- a/poezio/config.py +++ b/poezio/config.py @@ -165,7 +165,7 @@ class Config(RawConfigParser): def __init__(self, file_name: Path, default=None) -> None: RawConfigParser.__init__(self, None) # make the options case sensitive - self.optionxform = str + self.optionxform = lambda param: str(param) self.file_name = file_name self.read_file() self.default = default @@ -205,7 +205,7 @@ class Config(RawConfigParser): else: res = self.getstr(option, section) except (NoOptionError, NoSectionError, ValueError, AttributeError): - return default + return default or '' if res is None: return default diff --git a/poezio/core/core.py b/poezio/core/core.py index 580e4c76..3f4e6b3b 100644 --- a/poezio/core/core.py +++ b/poezio/core/core.py @@ -1082,7 +1082,7 @@ class Core: return new_tab def open_private_window(self, room_name: str, user_nick: str, - focus=True) -> tabs.PrivateTab: + focus=True) -> Optional[tabs.PrivateTab]: """ Open a Private conversation in a MUC and focus if needed. """ @@ -1193,13 +1193,13 @@ class Core: if tab is not None: # display the message in private tab.update_status(status) - def close_tab(self, tab: tabs.Tab = None): + def close_tab(self, to_close: tabs.Tab = None): """ Close the given tab. If None, close the current one """ - was_current = tab is None - if tab is None: - tab = self.tabs.current_tab + was_current = to_close is None + tab = to_close or self.tabs.current_tab + if isinstance(tab, tabs.RosterInfoTab): return # The tab 0 should NEVER be closed tab.on_close() diff --git a/poezio/core/tabs.py b/poezio/core/tabs.py index b8c6d3a7..bcf6dd41 100644 --- a/poezio/core/tabs.py +++ b/poezio/core/tabs.py @@ -44,7 +44,7 @@ class Tabs: '_events', ] - def __init__(self, events: EventHandler): + def __init__(self, events: EventHandler) -> None: """ Initialize the Tab List. Even though the list is initially empty, all methods are only valid once append() has been called @@ -111,7 +111,7 @@ class Tabs: """Return the tab list""" return self._tabs - def by_name(self, name: str) -> tabs.Tab: + def by_name(self, name: str) -> Optional[tabs.Tab]: """Get a tab with a specific name""" return self._tab_names.get(name) diff --git a/poezio/keyboard.py b/poezio/keyboard.py index 9033a752..3d8e8d5c 100755 --- a/poezio/keyboard.py +++ b/poezio/keyboard.py @@ -144,7 +144,7 @@ if __name__ == '__main__': s = curses.initscr() curses.noecho() curses.cbreak() - s.keypad(1) + s.keypad(True) curses.start_color() curses.use_default_colors() curses.init_pair(1, 2, -1) diff --git a/poezio/tabs/adhoc_commands_list.py b/poezio/tabs/adhoc_commands_list.py index fecfc9e2..b62166b0 100644 --- a/poezio/tabs/adhoc_commands_list.py +++ b/poezio/tabs/adhoc_commands_list.py @@ -5,16 +5,19 @@ nothing. """ import logging -log = logging.getLogger(__name__) +from typing import Dict, Callable from poezio.tabs import ListTab +from poezio.core.structs import Command from slixmpp.plugins.xep_0030.stanza.items import DiscoItem +log = logging.getLogger(__name__) + class AdhocCommandsListTab(ListTab): - plugin_commands = {} - plugin_keys = {} + plugin_commands = {} # type: Dict[str, Command] + plugin_keys = {} # type: Dict[str, Callable] def __init__(self, core, jid): ListTab.__init__( diff --git a/poezio/tabs/basetabs.py b/poezio/tabs/basetabs.py index 6a35bb51..578668fc 100644 --- a/poezio/tabs/basetabs.py +++ b/poezio/tabs/basetabs.py @@ -90,8 +90,11 @@ SHOW_NAME = { class Tab: - plugin_commands = {} + plugin_commands = {} # type: Dict[str, Command] plugin_keys = {} # type: Dict[str, Callable] + # Placeholder values, set on resize + height = 1 + width = 1 def __init__(self, core): self.core = core @@ -455,8 +458,8 @@ class ChatTab(Tab): Also, ^M is already bound to on_enter And also, add the /say command """ - plugin_commands = {} - plugin_keys = {} + plugin_commands = {} # type: Dict[str, Command] + plugin_keys = {} # type: Dict[str, Callable] message_type = 'chat' def __init__(self, core, jid=''): diff --git a/poezio/tabs/bookmarkstab.py b/poezio/tabs/bookmarkstab.py index 1ee623c5..816402a7 100644 --- a/poezio/tabs/bookmarkstab.py +++ b/poezio/tabs/bookmarkstab.py @@ -3,27 +3,31 @@ Defines the data-forms Tab """ import logging -log = logging.getLogger(__name__) +from typing import Dict, Callable, List from poezio import windows from poezio.bookmarks import Bookmark, BookmarkList +from poezio.core.structs import Command from poezio.tabs import Tab from poezio.common import safeJID +log = logging.getLogger(__name__) + class BookmarksTab(Tab): """ A tab displaying lines of bookmarks, each bookmark having a 4 widgets to set the jid/password/autojoin/storage method """ - plugin_commands = {} + plugin_commands = {} # type: Dict[str, Command] + plugin_keys = {} # type: Dict[str, Callable] def __init__(self, core, bookmarks: BookmarkList): Tab.__init__(self, core) self.name = "Bookmarks" self.bookmarks = bookmarks - self.new_bookmarks = [] - self.removed_bookmarks = [] + self.new_bookmarks = [] # type: List[Bookmark] + self.removed_bookmarks = [] # type: List[Bookmark] self.header_win = windows.ColumnHeaderWin( ('name', 'room@server/nickname', 'password', 'autojoin', 'storage')) diff --git a/poezio/tabs/confirmtab.py b/poezio/tabs/confirmtab.py index 545bb761..c76883dd 100644 --- a/poezio/tabs/confirmtab.py +++ b/poezio/tabs/confirmtab.py @@ -3,15 +3,18 @@ A generic tab that displays a text and a boolean choice """ import logging -log = logging.getLogger(__name__) +from typing import Dict, Callable from poezio import windows +from poezio.core.structs import Command from poezio.tabs import Tab +log = logging.getLogger(__name__) + class ConfirmTab(Tab): - plugin_commands = {} - plugin_keys = {} + plugin_commands = {} # type: Dict[str, Command] + plugin_keys = {} # type: Dict[str, Callable] def __init__(self, core, diff --git a/poezio/tabs/conversationtab.py b/poezio/tabs/conversationtab.py index 0d68b9b8..7e7a7488 100644 --- a/poezio/tabs/conversationtab.py +++ b/poezio/tabs/conversationtab.py @@ -11,10 +11,9 @@ There are two different instances of a ConversationTab: the time. """ -import logging -log = logging.getLogger(__name__) - import curses +import logging +from typing import Dict, Callable from poezio.tabs.basetabs import OneToOneTab, Tab @@ -23,21 +22,24 @@ from poezio import windows from poezio import xhtml from poezio.common import safeJID from poezio.config import config +from poezio.core.structs import Command from poezio.decorators import refresh_wrapper from poezio.roster import roster from poezio.text_buffer import CorrectionError from poezio.theming import get_theme, dump_tuple from poezio.decorators import command_args_parser +log = logging.getLogger(__name__) + class ConversationTab(OneToOneTab): """ The tab containg a normal conversation (not from a MUC) Must not be instantiated, use Static or Dynamic version only. """ - plugin_commands = {} - plugin_keys = {} - additional_information = {} + plugin_commands = {} # type: Dict[str, Command] + plugin_keys = {} # type: Dict[str, Callable] + additional_information = {} # type: Dict[str, Callable[[str], str]] message_type = 'chat' def __init__(self, core, jid): @@ -409,8 +411,8 @@ class DynamicConversationTab(ConversationTab): bad idea so it has been removed. Only one DynamicConversationTab can be opened for a given jid. """ - plugin_commands = {} - plugin_keys = {} + plugin_commands = {} # type: Dict[str, Command] + plugin_keys = {} # type: Dict[str, Callable] def __init__(self, core, jid, resource=None): self.locked_resource = None @@ -479,8 +481,8 @@ class StaticConversationTab(ConversationTab): A conversation tab associated with one Full JID. It cannot be locked to an different resource or unlocked. """ - plugin_commands = {} - plugin_keys = {} + plugin_commands = {} # type: Dict[str, Command] + plugin_keys = {} # type: Dict[str, Callable] def __init__(self, core, jid): assert (safeJID(jid).resource) diff --git a/poezio/tabs/data_forms.py b/poezio/tabs/data_forms.py index d216d4ca..496863bc 100644 --- a/poezio/tabs/data_forms.py +++ b/poezio/tabs/data_forms.py @@ -3,10 +3,13 @@ Defines the data-forms Tab """ import logging -log = logging.getLogger(__name__) +from typing import Dict, Callable from poezio import windows from poezio.tabs import Tab +from poezio.core.structs import Command + +log = logging.getLogger(__name__) class DataFormsTab(Tab): @@ -14,7 +17,8 @@ class DataFormsTab(Tab): A tab contaning various window type, displaying a form that the user needs to fill. """ - plugin_commands = {} + plugin_commands = {} # type: Dict[str, Command] + plugin_keys = {} # type: Dict[str, Callable] def __init__(self, core, form, on_cancel, on_send, kwargs): Tab.__init__(self, core) diff --git a/poezio/tabs/listtab.py b/poezio/tabs/listtab.py index 1c96f778..6a4da08e 100644 --- a/poezio/tabs/listtab.py +++ b/poezio/tabs/listtab.py @@ -4,21 +4,22 @@ sortable list. It should be inherited, to actually provide methods that insert items in the list, and that lets the user interact with them. """ -import logging -log = logging.getLogger(__name__) - import curses import collections +import logging +from typing import Dict, Callable from poezio import windows +from poezio.core.structs import Command from poezio.decorators import refresh_wrapper - from poezio.tabs import Tab +log = logging.getLogger(__name__) + class ListTab(Tab): - plugin_commands = {} - plugin_keys = {} + plugin_commands = {} # type: Dict[str, Command] + plugin_keys = {} # type: Dict[str, Callable] def __init__(self, core, name, help_message, header_text, cols): """Parameters: diff --git a/poezio/tabs/muclisttab.py b/poezio/tabs/muclisttab.py index 6ba7816d..aac25787 100644 --- a/poezio/tabs/muclisttab.py +++ b/poezio/tabs/muclisttab.py @@ -5,20 +5,23 @@ It has no functionality except scrolling the list, and allowing the user to join the rooms. """ import logging -log = logging.getLogger(__name__) +from typing import Dict, Callable from poezio.tabs import ListTab +from poezio.core.structs import Command from slixmpp.plugins.xep_0030.stanza.items import DiscoItem +log = logging.getLogger(__name__) + class MucListTab(ListTab): """ A tab listing rooms from a specific server, displaying various information, scrollable, and letting the user join them, etc """ - plugin_commands = {} - plugin_keys = {} + plugin_commands = {} # type: Dict[str, Command] + plugin_keys = {} # type: Dict[str, Callable] def __init__(self, core, server): ListTab.__init__(self, core, server.full, "“j”: join room.", diff --git a/poezio/tabs/muctab.py b/poezio/tabs/muctab.py index 4ec973a9..934dc0b1 100644 --- a/poezio/tabs/muctab.py +++ b/poezio/tabs/muctab.py @@ -7,15 +7,14 @@ It keeps track of many things such as part/joins, maintains an user list, and updates private tabs when necessary. """ -import logging -log = logging.getLogger(__name__) - import bisect import curses +import logging import os import random import re from datetime import datetime +from typing import Dict, Callable from poezio.tabs import ChatTab, Tab, SHOW_NAME @@ -27,6 +26,7 @@ from poezio import windows from poezio import xhtml from poezio.common import safeJID from poezio.config import config +from poezio.core.structs import Command from poezio.decorators import refresh_wrapper, command_args_parser from poezio.logger import logger from poezio.roster import roster @@ -34,6 +34,8 @@ from poezio.theming import get_theme, dump_tuple from poezio.user import User from poezio.core.structs import Completion, Status +log = logging.getLogger(__name__) + NS_MUC_USER = 'http://jabber.org/protocol/muc#user' STATUS_XPATH = '{%s}x/{%s}status' % (NS_MUC_USER, NS_MUC_USER) @@ -44,8 +46,8 @@ class MucTab(ChatTab): It contains an userlist, an input, a topic, an information and a chat zone """ message_type = 'groupchat' - plugin_commands = {} - plugin_keys = {} + plugin_commands = {} # type: Dict[str, Command] + plugin_keys = {} # type: Dict[str, Callable] def __init__(self, core, jid, nick, password=None): ChatTab.__init__(self, core, jid) diff --git a/poezio/tabs/privatetab.py b/poezio/tabs/privatetab.py index bc7f31c7..8f5f4d6f 100644 --- a/poezio/tabs/privatetab.py +++ b/poezio/tabs/privatetab.py @@ -10,10 +10,9 @@ both participant’s nicks. It also has slightly different features than the ConversationTab (such as tab-completion on nicks from the room). """ -import logging -log = logging.getLogger(__name__) - import curses +import logging +from typing import Dict, Callable from poezio.tabs import OneToOneTab, MucTab, Tab @@ -21,20 +20,23 @@ from poezio import windows from poezio import xhtml from poezio.common import safeJID from poezio.config import config +from poezio.core.structs import Command from poezio.decorators import refresh_wrapper from poezio.logger import logger from poezio.theming import get_theme, dump_tuple from poezio.decorators import command_args_parser +log = logging.getLogger(__name__) + class PrivateTab(OneToOneTab): """ The tab containg a private conversation (someone from a MUC) """ + plugin_commands = {} # type: Dict[str, Command] + plugin_keys = {} # type: Dict[str, Callable] message_type = 'chat' - plugin_commands = {} - additional_information = {} - plugin_keys = {} + additional_information = {} # type: Dict[str, Callable[[str], str]] def __init__(self, core, name, nick): OneToOneTab.__init__(self, core, name) diff --git a/poezio/tabs/rostertab.py b/poezio/tabs/rostertab.py index 2941159c..43c612d0 100644 --- a/poezio/tabs/rostertab.py +++ b/poezio/tabs/rostertab.py @@ -6,16 +6,15 @@ rectangle shows the current contact info. This module also includes functions to match users in the roster. """ import logging -log = logging.getLogger(__name__) - import base64 import curses import difflib import os import ssl -from os import getenv, path from functools import partial +from os import getenv, path from pathlib import Path +from typing import Dict, Callable from poezio import common from poezio import windows @@ -26,17 +25,18 @@ from poezio.decorators import refresh_wrapper from poezio.roster import RosterGroup, roster from poezio.theming import get_theme, dump_tuple from poezio.decorators import command_args_parser -from poezio.core.structs import Completion - +from poezio.core.structs import Command, Completion from poezio.tabs import Tab +log = logging.getLogger(__name__) + class RosterInfoTab(Tab): """ A tab, splitted in two, containing the roster and infos """ - plugin_commands = {} - plugin_keys = {} + plugin_commands = {} # type: Dict[str, Command] + plugin_keys = {} # type: Dict[str, Callable] def __init__(self, core): Tab.__init__(self, core) diff --git a/poezio/theming.py b/poezio/theming.py index 32ff8041..6491e03c 100755 --- a/poezio/theming.py +++ b/poezio/theming.py @@ -498,9 +498,9 @@ def update_themes_dir(option: Optional[str] = None, load_path.append(default_dir) # import from the user-defined prefs - themes_dir = config.get('themes_dir') - themes_dir = Path( - themes_dir).expanduser() if themes_dir else xdg.DATA_HOME / 'themes' + themes_dir_str = config.get('themes_dir') + themes_dir = Path(themes_dir_str).expanduser( + ) if themes_dir_str else xdg.DATA_HOME / 'themes' try: themes_dir.mkdir(parents=True, exist_ok=True) except OSError: diff --git a/poezio/user.py b/poezio/user.py index 3792eca8..655eb0de 100644 --- a/poezio/user.py +++ b/poezio/user.py @@ -39,7 +39,7 @@ class User: role: str, jid: JID, deterministic=True, - color=''): + color='') -> None: # The oldest possible time self.last_talked = datetime(1, 1, 1) # type: datetime self.update(affiliation, show, status, role) diff --git a/poezio/windows/inputs.py b/poezio/windows/inputs.py index a0f97918..8ff420fd 100644 --- a/poezio/windows/inputs.py +++ b/poezio/windows/inputs.py @@ -2,11 +2,10 @@ Text inputs. """ -import logging -log = logging.getLogger(__name__) - import curses +import logging import string +from typing import List from poezio import keyboard from poezio import common @@ -16,6 +15,8 @@ from poezio.windows.funcs import find_first_format_char from poezio.config import config from poezio.theming import to_curses_attr +log = logging.getLogger(__name__) + DEFAULT_ON_INPUT = lambda x: None @@ -583,7 +584,7 @@ class HistoryInput(Input): An input with colors and stuff, plus an history ^R allows to search inside the history (as in a shell) """ - history = [] + history = [] # type: List[str] def __init__(self): Input.__init__(self) @@ -593,7 +594,7 @@ class HistoryInput(Input): self.key_func['^R'] = self.toggle_search self.search = False if config.get('separate_history'): - self.history = [] + self.history = [] # type: List[str] def toggle_search(self): if self.help_message: @@ -669,7 +670,8 @@ class MessageInput(HistoryInput): Conversation, Muc and Private tabs Also letting the user enter colors or other text markups """ - history = [] # The history is common to all MessageInput + # The history is common to all MessageInput + history = [] # type: List[str] def __init__(self): HistoryInput.__init__(self) @@ -716,7 +718,7 @@ class CommandInput(HistoryInput): HelpMessage when a command is started The on_input callback """ - history = [] + history = [] # type: List[str] def __init__(self, help_message, on_abort, on_success, on_input=None): HistoryInput.__init__(self) -- cgit v1.2.3