diff options
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> | 2020-12-12 18:44:37 +0100 |
---|---|---|
committer | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> | 2020-12-12 19:36:18 +0100 |
commit | 65b8046fe08a19df937068e5fe5ad15f9b0a785a (patch) | |
tree | 827e17a99d39c5db453d0fc0e9b46249292aa4e3 /poezio | |
parent | 34ec9e3ee1384506b2e803bdfe94201a7b7ff4c3 (diff) | |
download | poezio-65b8046fe08a19df937068e5fe5ad15f9b0a785a.tar.gz poezio-65b8046fe08a19df937068e5fe5ad15f9b0a785a.tar.bz2 poezio-65b8046fe08a19df937068e5fe5ad15f9b0a785a.tar.xz poezio-65b8046fe08a19df937068e5fe5ad15f9b0a785a.zip |
from __future__ import annotations
Now that our baseline is Python 3.7, we can rely on type annotations to
be lazily evaluated.
Diffstat (limited to 'poezio')
46 files changed, 180 insertions, 166 deletions
diff --git a/poezio/bookmarks.py b/poezio/bookmarks.py index d842d2dd..4ce06cf0 100644 --- a/poezio/bookmarks.py +++ b/poezio/bookmarks.py @@ -152,7 +152,7 @@ class Bookmark: class BookmarkList: def __init__(self): - self.bookmarks = [] # type: List[Bookmark] + self.bookmarks: List[Bookmark] = [] preferred = config.get('use_bookmarks_method').lower() if preferred not in ('pep', 'privatexml'): preferred = 'privatexml' diff --git a/poezio/colors.py b/poezio/colors.py index c1019145..adb2ca40 100644 --- a/poezio/colors.py +++ b/poezio/colors.py @@ -37,7 +37,7 @@ def ncurses_color_to_rgb(color: int) -> Tuple[float, float, float]: def generate_ccg_palette(curses_palette: List[int], reference_y: float) -> Palette: - cbcr_palette = {} # type: Dict[float, Tuple[float, int]] + cbcr_palette: Dict[float, Tuple[float, int]] = {} for curses_color in curses_palette: r, g, b = ncurses_color_to_rgb(curses_color) # drop grayscale diff --git a/poezio/common.py b/poezio/common.py index 315d5b9e..5332d408 100644 --- a/poezio/common.py +++ b/poezio/common.py @@ -250,7 +250,7 @@ def find_delayed_tag(message: Message) -> Tuple[bool, Optional[datetime]]: find_delay = message.xml.find delay_tag = find_delay('{urn:xmpp:delay}delay') - date = None # type: Optional[datetime] + date: Optional[datetime] = None if delay_tag is not None: delayed = True date = _datetime_tuple(delay_tag.attrib['stamp']) diff --git a/poezio/config.py b/poezio/config.py index 9a51e53f..78581775 100644 --- a/poezio/config.py +++ b/poezio/config.py @@ -383,8 +383,7 @@ class Config(RawConfigParser): if file_ok(self.file_name): try: with self.file_name.open('r', encoding='utf-8') as df: - lines_before = [line.strip() - for line in df] # type: List[str] + lines_before: List[str] = [line.strip() for line in df] except OSError: log.error( 'Unable to read the config file %s', @@ -394,7 +393,7 @@ class Config(RawConfigParser): else: lines_before = [] - sections = {} # type: Dict[str, List[int]] + sections: Dict[str, List[int]] = {} duplicate_section = False current_section = '' current_line = 0 diff --git a/poezio/contact.py b/poezio/contact.py index 50ccab1f..3330a2a6 100644 --- a/poezio/contact.py +++ b/poezio/contact.py @@ -29,8 +29,8 @@ class Resource: data: the dict to use as a source """ # Full JID - self._jid = jid # type: str - self._data = data # type: Dict[str, Union[str, int]] + self._jid: str = jid + self._data: Dict[str, Union[str, int]] = data @property def jid(self) -> str: @@ -69,12 +69,12 @@ class Contact: item: a slixmpp RosterItem pointing to that contact """ self.__item = item - self.folded_states = defaultdict(lambda: True) # type: Dict[str, bool] + self.folded_states: Dict[str, bool] = defaultdict(lambda: True) self._name = '' self.avatar = None self.error = None - self.tune = {} # type: Dict[str, str] - self.gaming = {} # type: Dict[str, str] + self.tune: Dict[str, str] = {} + self.gaming: Dict[str, str] = {} self.mood = '' self.activity = '' diff --git a/poezio/core/commands.py b/poezio/core/commands.py index e926dba5..cd957002 100644 --- a/poezio/core/commands.py +++ b/poezio/core/commands.py @@ -335,7 +335,7 @@ class CommandCore: except InvalidJID: return (None, None) - set_nick = '' # type: Optional[str] + set_nick: Optional[str] = '' if len(jid_string) > 1 and jid_string.startswith('/'): set_nick = jid_string[1:] elif info.resource: diff --git a/poezio/core/completions.py b/poezio/core/completions.py index ada8d2b9..98ca9ba0 100644 --- a/poezio/core/completions.py +++ b/poezio/core/completions.py @@ -490,7 +490,7 @@ class CompletionCore: tabs.StaticConversationTab, tabs.DynamicConversationTab, ) - tabjid = [] # type: List[JID] + tabjid: List[JID] = [] if isinstance(current_tab, chattabs): tabjid = [current_tab.jid.bare] diff --git a/poezio/core/core.py b/poezio/core/core.py index 3a13d4c3..2151600f 100644 --- a/poezio/core/core.py +++ b/poezio/core/core.py @@ -1171,7 +1171,7 @@ class Core: """ # shortcut priority = tabs.STATE_PRIORITY - tab_refs = {} # type: Dict[str, List[tabs.Tab]] + tab_refs: Dict[str, List[tabs.Tab]] = {} # put all the active tabs in a dict of lists by state for tab in self.tabs.get_tabs(): if not tab: diff --git a/poezio/core/tabs.py b/poezio/core/tabs.py index 61bad6f2..a789100d 100644 --- a/poezio/core/tabs.py +++ b/poezio/core/tabs.py @@ -54,16 +54,15 @@ class Tabs: once. Otherwise, mayhem is expected. """ # cursor - self._current_index = 0 # type: int - self._current_tab = None # type: Optional[tabs.Tab] - - self._previous_tab = None # type: Optional[tabs.Tab] - self._tabs = [] # type: List[tabs.Tab] - self._tab_jids = dict() # type: Dict[JID, tabs.Tab] - self._tab_types = defaultdict( - list) # type: Dict[Type[tabs.Tab], List[tabs.Tab]] - self._tab_names = dict() # type: Dict[str, tabs.Tab] - self._events = events # type: EventHandler + self._current_index: int = 0 + self._current_tab: Optional[tabs.Tab] = None + + self._previous_tab: Optional[tabs.Tab] = None + self._tabs: List[tabs.Tab] = [] + self._tab_jids: Dict[JID, tabs.Tab] = dict() + self._tab_types: Dict[Type[tabs.Tab], List[tabs.Tab]] = defaultdict(list) + self._tab_names: Dict[str, tabs.Tab] = dict() + self._events: EventHandler = events def __len__(self): return len(self._tabs) diff --git a/poezio/decorators.py b/poezio/decorators.py index 62724ecd..6a853446 100644 --- a/poezio/decorators.py +++ b/poezio/decorators.py @@ -1,6 +1,9 @@ """ Module containing various decorators """ + +from __future__ import annotations + from typing import ( cast, Any, @@ -179,7 +182,7 @@ command_args_parser = CommandArgParser() def deny_anonymous(func: Callable) -> Callable: """Decorator to disable commands when using an anonymous account.""" - def wrap(self: 'RosterInfoTab', *args: Any, **kwargs: Any) -> Any: + def wrap(self: RosterInfoTab, *args: Any, **kwargs: Any) -> Any: if self.core.xmpp.anon: return self.core.information( 'This command is not available for anonymous accounts.', diff --git a/poezio/events.py b/poezio/events.py index 5213f663..63782836 100644 --- a/poezio/events.py +++ b/poezio/events.py @@ -48,7 +48,7 @@ class EventHandler: 'ignored_private', 'tab_change', ] - self.events = {} # type: Dict[str, OrderedDict[int, List[Callable]]] + self.events: Dict[str, OrderedDict[int, List[Callable]]] = {} for event in events: self.events[event] = OrderedDict() diff --git a/poezio/keyboard.py b/poezio/keyboard.py index 3d8e8d5c..23da2e37 100755 --- a/poezio/keyboard.py +++ b/poezio/keyboard.py @@ -26,7 +26,7 @@ log = logging.getLogger(__name__) # shortcuts or inserting text in the current output. The callback # is always reset to None afterwards (to resume the normal # processing of keys) -continuation_keys_callback = None # type: Optional[Callable] +continuation_keys_callback: Optional[Callable] = None def get_next_byte(s) -> Tuple[Optional[int], Optional[bytes]]: @@ -46,7 +46,7 @@ def get_next_byte(s) -> Tuple[Optional[int], Optional[bytes]]: def get_char_list(s) -> List[str]: - ret_list = [] # type: List[str] + ret_list: List[str] = [] while True: try: key = s.get_wch() diff --git a/poezio/logger.py b/poezio/logger.py index 14882f00..579639e3 100644 --- a/poezio/logger.py +++ b/poezio/logger.py @@ -76,7 +76,7 @@ class Logger: def __init__(self): self._roster_logfile = None # Optional[IO[Any]] # a dict of 'groupchatname': file-object (opened) - self._fds = {} # type: Dict[str, IO[Any]] + self._fds: Dict[str, IO[Any]] = {} def __del__(self): for opened_file in self._fds.values(): diff --git a/poezio/mam.py b/poezio/mam.py index 31ca2f0c..b40ddc4d 100644 --- a/poezio/mam.py +++ b/poezio/mam.py @@ -111,10 +111,10 @@ async def get_mam_iterator( if 'urn:xmpp:mam:2' not in iq['disco_info'].get_features(): raise NoMAMSupportException() - args = { + args: Dict[str, Any] = { 'iterator': True, 'reverse': reverse, - } # type: Dict[str, Any] + } if groupchat: args['jid'] = remote_jid diff --git a/poezio/multiuserchat.py b/poezio/multiuserchat.py index f4383176..71b5cceb 100644 --- a/poezio/multiuserchat.py +++ b/poezio/multiuserchat.py @@ -10,6 +10,8 @@ Add some facilities that are not available on the XEP_0045 slix plugin """ +from __future__ import annotations + from xml.etree import ElementTree as ET from typing import ( Callable, @@ -103,7 +105,7 @@ def change_subject(xmpp: ClientXMPP, jid: JID, subject: str) -> None: def change_nick( - core: 'Core', + core: Core, jid: JID, nick: str, status: Optional[str] = None, @@ -120,14 +122,14 @@ def change_nick( def join_groupchat( - core: 'Core', + core: Core, jid: JID, nick: str, passwd: str = '', status: Optional[str] = None, show: Optional[str] = None, seconds: Optional[int] = None, - tab: Optional['Tab'] = None + tab: Optional[Tab] = None ) -> None: xmpp = core.xmpp stanza = xmpp.make_presence( diff --git a/poezio/pep.py b/poezio/pep.py index 52cc4cd5..dde97ed6 100644 --- a/poezio/pep.py +++ b/poezio/pep.py @@ -5,7 +5,7 @@ extracted directly from the XEP from typing import Dict -MOODS = { +MOODS: Dict[str, str] = { 'afraid': 'Afraid', 'amazed': 'Amazed', 'angry': 'Angry', @@ -86,9 +86,9 @@ MOODS = { 'undefined': 'Undefined', 'weak': 'Weak', 'worried': 'Worried' -} # type: Dict[str, str] +} -ACTIVITIES = { +ACTIVITIES: Dict[str, Dict[str, str]] = { 'doing_chores': { 'category': 'Doing_chores', 'buying_groceries': 'Buying groceries', @@ -204,4 +204,4 @@ ACTIVITIES = { 'studying': 'Studying', 'other': 'Other', } -} # type: Dict[str, Dict[str, str]] +} diff --git a/poezio/plugin_e2ee.py b/poezio/plugin_e2ee.py index 9d1d4903..a0856957 100644 --- a/poezio/plugin_e2ee.py +++ b/poezio/plugin_e2ee.py @@ -97,30 +97,30 @@ class E2EEPlugin(BasePlugin): #: Encryption name, used in command descriptions, and logs. At least one #: of `encryption_name` and `encryption_short_name` must be set. - encryption_name = None # type: Optional[str] + encryption_name: Optional[str] = None #: Encryption short name, used as command name, and also to display #: encryption status in a tab. At least one of `encryption_name` and #: `encryption_short_name` must be set. - encryption_short_name = None # type: Optional[str] + encryption_short_name: Optional[str] = None #: Required. https://xmpp.org/extensions/xep-0380.html. - eme_ns = None # type: Optional[str] + eme_ns: Optional[str] = None #: Used to figure out what messages to attempt decryption for. Also used #: in combination with `tag_whitelist` to avoid removing encrypted tags #: before sending. - encrypted_tags = None # type: Optional[List[Tuple[str, str]]] + encrypted_tags: Optional[List[Tuple[str, str]]] = None # Static map, to be able to limit to one encryption mechanism per tab at a # time - _enabled_tabs = {} # type: Dict[JID, Callable] + _enabled_tabs: Dict[JID, Callable] = {} # Tabs that support this encryption mechanism - supported_tab_types = tuple() # type: Tuple[ChatTabs] + supported_tab_types: Tuple[ChatTabs] = tuple() # States for each remote entity - trust_states = {'accepted': set(), 'rejected': set()} # type: Dict[str, Set[str]] + trust_states: Dict[str, Set[str]] = {'accepted': set(), 'rejected': set()} def init(self): self._all_trust_states = self.trust_states['accepted'].union( @@ -229,7 +229,7 @@ class E2EEPlugin(BasePlugin): return "" def _toggle_tab(self, _input: str) -> None: - jid = self.api.current_tab().jid # type: JID + jid: JID = self.api.current_tab().jid if self._encryption_enabled(jid): del self._enabled_tabs[jid] @@ -394,7 +394,7 @@ class E2EEPlugin(BasePlugin): # Find who to encrypt to. If in a groupchat this can be multiple JIDs. # It is possible that we are not able to find a jid (e.g., semi-anon # MUCs). Let the plugin decide what to do with this information. - jids = [message['to']] # type: Optional[List[JID]] + jids: Optional[List[JID]] = [message['to']] tab = self.core.tabs.by_jid(message['to']) if tab is None: # When does that ever happen? log.debug('Attempting to encrypt a message to \'%s\' ' diff --git a/poezio/tabs/adhoc_commands_list.py b/poezio/tabs/adhoc_commands_list.py index b62166b0..3b6bc1db 100644 --- a/poezio/tabs/adhoc_commands_list.py +++ b/poezio/tabs/adhoc_commands_list.py @@ -16,8 +16,8 @@ log = logging.getLogger(__name__) class AdhocCommandsListTab(ListTab): - plugin_commands = {} # type: Dict[str, Command] - plugin_keys = {} # type: Dict[str, Callable] + plugin_commands: Dict[str, Command] = {} + plugin_keys: Dict[str, Callable] = {} def __init__(self, core, jid): ListTab.__init__( diff --git a/poezio/tabs/basetabs.py b/poezio/tabs/basetabs.py index e4cdc3af..3907d7bc 100644 --- a/poezio/tabs/basetabs.py +++ b/poezio/tabs/basetabs.py @@ -13,6 +13,8 @@ This module also defines ChatTabs, the parent class for all tabs revolving around chats. """ +from __future__ import annotations + import copy import logging import string @@ -111,13 +113,13 @@ SHOW_NAME = { class Tab: - plugin_commands = {} # type: Dict[str, Command] - plugin_keys = {} # type: Dict[str, Callable] + plugin_commands: Dict[str, Command] = {} + plugin_keys: Dict[str, Callable] = {} # Placeholder values, set on resize height = 1 width = 1 - def __init__(self, core: 'Core'): + def __init__(self, core: Core): self.core = core self.nb = 0 if not hasattr(self, 'name'): @@ -133,7 +135,7 @@ class Tab: self.commands = {} # and their own commands @property - def size(self) -> 'SizeManager': + def size(self) -> SizeManager: return self.core.size @staticmethod @@ -196,7 +198,7 @@ class Tab: self._state = 'normal' @staticmethod - def initial_resize(scr: '_CursesWindow'): + def initial_resize(scr: _CursesWindow): Tab.height, Tab.width = scr.getmaxyx() windows.base_wins.TAB_WIN = scr @@ -479,8 +481,8 @@ class ChatTab(Tab): Also, ^M is already bound to on_enter And also, add the /say command """ - plugin_commands = {} # type: Dict[str, Command] - plugin_keys = {} # type: Dict[str, Callable] + plugin_commands: Dict[str, Command] = {} + plugin_keys: Dict[str, Callable] = {} message_type = 'chat' def __init__(self, core, jid: Union[JID, str]): @@ -492,7 +494,7 @@ class ChatTab(Tab): self._jid = jid #: Is the tab currently requesting MAM data? self.query_status = False - self._name = jid.full # type: Optional[str] + self._name: Optional[str] = jid.full self.text_win = windows.TextWin() self.directed_presence = None self._text_buffer = TextBuffer() @@ -532,7 +534,7 @@ class ChatTab(Tab): desc='Fix the last message with whatever you want.', shortdesc='Correct the last message.', completion=self.completion_correct) - self.chat_state = None # type: Optional[str] + self.chat_state: Optional[str] = None self.update_commands() self.update_keys() diff --git a/poezio/tabs/bookmarkstab.py b/poezio/tabs/bookmarkstab.py index eb390bd3..c4fdadd3 100644 --- a/poezio/tabs/bookmarkstab.py +++ b/poezio/tabs/bookmarkstab.py @@ -21,15 +21,15 @@ 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 = {} # type: Dict[str, Command] - plugin_keys = {} # type: Dict[str, Callable] + plugin_commands: Dict[str, Command] = {} + plugin_keys: Dict[str, Callable] = {} def __init__(self, core, bookmarks: BookmarkList): Tab.__init__(self, core) self.name = "Bookmarks" self.bookmarks = bookmarks - self.new_bookmarks = [] # type: List[Bookmark] - self.removed_bookmarks = [] # type: List[Bookmark] + self.new_bookmarks: List[Bookmark] = [] + self.removed_bookmarks: 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 c13de4a6..89d0daf5 100644 --- a/poezio/tabs/confirmtab.py +++ b/poezio/tabs/confirmtab.py @@ -13,8 +13,8 @@ log = logging.getLogger(__name__) class ConfirmTab(Tab): - plugin_commands = {} # type: Dict[str, Command] - plugin_keys = {} # type: Dict[str, Callable] + plugin_commands: Dict[str, Command] = {} + plugin_keys: Dict[str, Callable] = {} def __init__(self, core, diff --git a/poezio/tabs/conversationtab.py b/poezio/tabs/conversationtab.py index 5950e4cb..5d62fa5f 100644 --- a/poezio/tabs/conversationtab.py +++ b/poezio/tabs/conversationtab.py @@ -38,9 +38,9 @@ class ConversationTab(OneToOneTab): The tab containing a normal conversation (not from a MUC) Must not be instantiated, use Static or Dynamic version only. """ - plugin_commands = {} # type: Dict[str, Command] - plugin_keys = {} # type: Dict[str, Callable] - additional_information = {} # type: Dict[str, Callable[[str], str]] + plugin_commands: Dict[str, Command] = {} + plugin_keys: Dict[str, Callable] = {} + additional_information: Dict[str, Callable[[str], str]] = {} message_type = 'chat' def __init__(self, core, jid): @@ -377,8 +377,8 @@ class DynamicConversationTab(ConversationTab): bad idea so it has been removed. Only one DynamicConversationTab can be opened for a given jid. """ - plugin_commands = {} # type: Dict[str, Command] - plugin_keys = {} # type: Dict[str, Callable] + plugin_commands: Dict[str, Command] = {} + plugin_keys: Dict[str, Callable] = {} def __init__(self, core, jid, resource=None): self.locked_resource = None @@ -447,8 +447,8 @@ class StaticConversationTab(ConversationTab): A conversation tab associated with one Full JID. It cannot be locked to an different resource or unlocked. """ - plugin_commands = {} # type: Dict[str, Command] - plugin_keys = {} # type: Dict[str, Callable] + plugin_commands: Dict[str, Command] = {} + plugin_keys: Dict[str, Callable] = {} def __init__(self, core, jid): ConversationTab.__init__(self, core, jid) diff --git a/poezio/tabs/data_forms.py b/poezio/tabs/data_forms.py index f4ed63e5..8e13a84c 100644 --- a/poezio/tabs/data_forms.py +++ b/poezio/tabs/data_forms.py @@ -17,8 +17,8 @@ class DataFormsTab(Tab): A tab containing various window type, displaying a form that the user needs to fill. """ - plugin_commands = {} # type: Dict[str, Command] - plugin_keys = {} # type: Dict[str, Callable] + plugin_commands: Dict[str, Command] = {} + plugin_keys: 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 87e7d9f4..3489eb9c 100644 --- a/poezio/tabs/listtab.py +++ b/poezio/tabs/listtab.py @@ -18,8 +18,8 @@ log = logging.getLogger(__name__) class ListTab(Tab): - plugin_commands = {} # type: Dict[str, Command] - plugin_keys = {} # type: Dict[str, Callable] + plugin_commands: Dict[str, Command] = {} + plugin_keys: 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 4c1e492f..f6b3fc35 100644 --- a/poezio/tabs/muclisttab.py +++ b/poezio/tabs/muclisttab.py @@ -20,8 +20,8 @@ class MucListTab(ListTab): A tab listing rooms from a specific server, displaying various information, scrollable, and letting the user join them, etc """ - plugin_commands = {} # type: Dict[str, Command] - plugin_keys = {} # type: Dict[str, Callable] + plugin_commands: Dict[str, Command] = {} + plugin_keys: 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 182e7145..88fb5419 100644 --- a/poezio/tabs/muctab.py +++ b/poezio/tabs/muctab.py @@ -7,6 +7,8 @@ It keeps track of many things such as part/joins, maintains an user list, and updates private tabs when necessary. """ +from __future__ import annotations + import asyncio import bisect import curses @@ -78,38 +80,38 @@ class MucTab(ChatTab): It contains a userlist, an input, a topic, an information and a chat zone """ message_type = 'groupchat' - plugin_commands = {} # type: Dict[str, Command] - plugin_keys = {} # type: Dict[str, Callable[..., Any]] - additional_information = {} # type: Dict[str, Callable[[str], str]] + plugin_commands: Dict[str, Command] = {} + plugin_keys: Dict[str, Callable[..., Any]] = {} + additional_information: Dict[str, Callable[[str], str]] = {} lagged = False - def __init__(self, core: 'Core', jid: JID, nick: str, password: Optional[str] = None) -> None: + def __init__(self, core: Core, jid: JID, nick: str, password: Optional[str] = None) -> None: ChatTab.__init__(self, core, jid) self.joined = False self._state = 'disconnected' # our nick in the MUC self.own_nick = nick # self User object - self.own_user = None # type: Optional[User] + self.own_user: Optional[User] = None self.password = password # buffered presences - self.presence_buffer = [] # type: List[Presence] + self.presence_buffer: List[Presence] = [] # userlist - self.users = [] # type: List[User] + self.users: List[User] = [] # private conversations - self.privates = [] # type: List[Tab] + self.privates: List[Tab] = [] self.topic = '' self.topic_from = '' # Self ping event, so we can cancel it when we leave the room - self.self_ping_event = None # type: Optional[timed_events.DelayedEvent] + self.self_ping_event: Optional[timed_events.DelayedEvent] = None # UI stuff self.topic_win = windows.Topic() self.v_separator = windows.VerticalSeparator() self.user_win = windows.UserList() self.info_header = windows.MucInfoWin() - self.input = windows.MessageInput() # type: windows.MessageInput + self.input: windows.MessageInput = windows.MessageInput() # List of ignored users - self.ignores = [] # type: List[User] + self.ignores: List[User] = [] # keys self.register_keys() self.update_keys() @@ -149,14 +151,14 @@ class MucTab(ChatTab): """ del MucTab.additional_information[plugin_name] - def cancel_config(self, form: 'Form') -> None: + def cancel_config(self, form: Form) -> None: """ The user do not want to send their config, send an iq cancel """ asyncio.ensure_future(self.core.xmpp['xep_0045'].cancel_config(self.jid.bare)) self.core.close_tab() - def send_config(self, form: 'Form') -> None: + def send_config(self, form: Form) -> None: """ The user sends their config to the server """ @@ -1406,7 +1408,7 @@ class MucTab(ChatTab): /configure """ - def on_form_received(form: 'Form') -> None: + def on_form_received(form: Form) -> None: if not form: self.core.information( 'Could not retrieve the configuration form', 'Error') diff --git a/poezio/tabs/privatetab.py b/poezio/tabs/privatetab.py index f29e302c..54b9a15d 100644 --- a/poezio/tabs/privatetab.py +++ b/poezio/tabs/privatetab.py @@ -35,10 +35,10 @@ class PrivateTab(OneToOneTab): """ The tab containing a private conversation (someone from a MUC) """ - plugin_commands = {} # type: Dict[str, Command] - plugin_keys = {} # type: Dict[str, Callable] + plugin_commands: Dict[str, Command] = {} + plugin_keys: Dict[str, Callable] = {} message_type = 'chat' - additional_information = {} # type: Dict[str, Callable[[str], str]] + additional_information: Dict[str, Callable[[str], str]] = {} def __init__(self, core, jid, nick): OneToOneTab.__init__(self, core, jid) diff --git a/poezio/tabs/rostertab.py b/poezio/tabs/rostertab.py index 072e0776..15a59455 100644 --- a/poezio/tabs/rostertab.py +++ b/poezio/tabs/rostertab.py @@ -36,8 +36,8 @@ class RosterInfoTab(Tab): """ A tab, split in two, containing the roster and infos """ - plugin_commands = {} # type: Dict[str, Command] - plugin_keys = {} # type: Dict[str, Callable] + plugin_commands: Dict[str, Command] = {} + plugin_keys: Dict[str, Callable] = {} def __init__(self, core): Tab.__init__(self, core) diff --git a/poezio/text_buffer.py b/poezio/text_buffer.py index 6ef8e3d4..89bae3a2 100644 --- a/poezio/text_buffer.py +++ b/poezio/text_buffer.py @@ -8,6 +8,8 @@ Each text buffer can be linked to multiple windows, that will be rendered independently by their TextWins. """ +from __future__ import annotations + import logging log = logging.getLogger(__name__) @@ -62,23 +64,23 @@ class TextBuffer: if messages_nb_limit is None: messages_nb_limit = cast(int, config.get('max_messages_in_memory')) - self._messages_nb_limit = messages_nb_limit # type: int + self._messages_nb_limit: int = messages_nb_limit # Message objects - self.messages = [] # type: List[BaseMessage] + self.messages: List[BaseMessage] = [] # COMPAT: Correction id -> Original message id. - self.correction_ids = {} # type: Dict[str, str] + self.correction_ids: Dict[str, str] = {} # we keep track of one or more windows # so we can pass the new messages to them, as they are added, so # they (the windows) can build the lines from the new message - self._windows = [] # type: List[TextWin] + self._windows: List[TextWin] = [] def add_window(self, win) -> None: self._windows.append(win) def find_last_gap_muc(self) -> Optional[HistoryGap]: """Find the last known history gap contained in buffer""" - leave = None # type:Optional[Tuple[int, BaseMessage]] - join = None # type:Optional[Tuple[int, BaseMessage]] + leave: Optional[Tuple[int, BaseMessage]] = None + join: Optional[Tuple[int, BaseMessage]] = None for i, item in enumerate(reversed(self.messages)): if isinstance(item, MucOwnLeaveMessage): leave = (len(self.messages) - i - 1, item) @@ -250,7 +252,7 @@ class TextBuffer: new_id: str, highlight: bool = False, time: Optional[datetime] = None, - user: Optional['User'] = None, + user: Optional[User] = None, jid: Optional[str] = None) -> Message: """ Correct a message in a text buffer. diff --git a/poezio/theming.py b/poezio/theming.py index 7752fe15..6245a48d 100755 --- a/poezio/theming.py +++ b/poezio/theming.py @@ -291,7 +291,7 @@ class Theme: (224, -1), (225, -1), (226, -1), (227, -1)] # XEP-0392 consistent color generation palette placeholder # it’s generated on first use when accessing the ccg_palette property - CCG_PALETTE = None # type: Optional[Dict[float, int]] + CCG_PALETTE: Optional[Dict[float, int]] = None CCG_Y = 0.5**0.45 # yapf: enable @@ -393,8 +393,7 @@ theme = Theme() # Each time we use a color tuple, we check if it has already been used. # If not we create a new color_pair and keep it in that dict, to use it # the next time. -curses_colors_dict = { -} # type: Dict[Union[Tuple[int, int], Tuple[int, int, str]], int] +curses_colors_dict: Dict[Union[Tuple[int, int], Tuple[int, int, str]], int] = {} # yapf: disable @@ -418,7 +417,7 @@ table_256_to_16 = [ ] # yapf: enable -load_path = [] # type: List[str] +load_path: List[str] = [] def color_256_to_16(color): diff --git a/poezio/timed_events.py b/poezio/timed_events.py index cd7659e2..3354443a 100644 --- a/poezio/timed_events.py +++ b/poezio/timed_events.py @@ -32,11 +32,11 @@ class DelayedEvent: :param function callback: The handler that will be executed. :param args: Optional arguments passed to the handler. """ - self.callback = callback # type: Callable - self.args = args # type: Tuple[Any, ...] - self.delay = delay # type: Union[int, float] + self.callback: Callable = callback + self.args: Tuple[Any, ...] = args + self.delay: Union[int, float] = delay # An asyncio handler, as returned by call_later() or call_at() - self.handler = None # type: Optional[Handle] + self.handler: Optional[Handle] = None class TimedEvent(DelayedEvent): diff --git a/poezio/ui/render.py b/poezio/ui/render.py index f37ea39e..13e493f1 100644 --- a/poezio/ui/render.py +++ b/poezio/ui/render.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import curses from datetime import ( @@ -52,7 +54,7 @@ LinePos = Tuple[int, int] def generate_lines(lines: List[LinePos], msg: BaseMessage, default_color: str = '') -> List[Line]: line_objects = [] - attrs = [] # type: List[str] + attrs: List[str] = [] prepend = default_color if default_color else '' for line in lines: saved = Line( @@ -114,7 +116,7 @@ def build_xmllog(msg: XMLLog, width: int, timestamp: bool, nick_size: int = 10) @singledispatch -def write_pre(msg: BaseMessage, win: 'Win', with_timestamps: bool, nick_size: int) -> int: +def write_pre(msg: BaseMessage, win: Win, with_timestamps: bool, nick_size: int) -> int: """Write the part before text (only the timestamp)""" if with_timestamps: return PreMessageHelpers.write_time(win, False, msg.time) @@ -122,7 +124,7 @@ def write_pre(msg: BaseMessage, win: 'Win', with_timestamps: bool, nick_size: in @write_pre.register(Message) -def write_pre_message(msg: Message, win: 'Win', with_timestamps: bool, nick_size: int) -> int: +def write_pre_message(msg: Message, win: Win, with_timestamps: bool, nick_size: int) -> int: """Write the part before the body: - timestamp (short or long) - ack/nack @@ -165,7 +167,7 @@ def write_pre_message(msg: Message, win: 'Win', with_timestamps: bool, nick_size @write_pre.register(XMLLog) -def write_pre_xmllog(msg: XMLLog, win: 'Win', with_timestamps: bool, nick_size: int) -> int: +def write_pre_xmllog(msg: XMLLog, win: Win, with_timestamps: bool, nick_size: int) -> int: """Write the part before the stanza (timestamp + IN/OUT)""" offset = 0 if with_timestamps: @@ -186,7 +188,7 @@ def write_pre_xmllog(msg: XMLLog, win: 'Win', with_timestamps: bool, nick_size: class PreMessageHelpers: @staticmethod - def write_revisions(buffer: 'Win', msg: Message) -> int: + def write_revisions(buffer: Win, msg: Message) -> int: if msg.revisions: color = get_theme().COLOR_REVISIONS_MESSAGE with buffer.colored_text(color=color): @@ -195,7 +197,7 @@ class PreMessageHelpers: return 0 @staticmethod - def write_ack(buffer: 'Win') -> int: + def write_ack(buffer: Win) -> int: theme = get_theme() color = theme.COLOR_CHAR_ACK with buffer.colored_text(color=color): @@ -204,7 +206,7 @@ class PreMessageHelpers: return poopt.wcswidth(theme.CHAR_ACK_RECEIVED) + 1 @staticmethod - def write_nack(buffer: 'Win') -> int: + def write_nack(buffer: Win) -> int: theme = get_theme() color = theme.COLOR_CHAR_NACK with buffer.colored_text(color=color): @@ -213,7 +215,7 @@ class PreMessageHelpers: return poopt.wcswidth(theme.CHAR_NACK) + 1 @staticmethod - def write_nickname(buffer: 'Win', nickname: str, color, highlight=False) -> None: + def write_nickname(buffer: Win, nickname: str, color, highlight=False) -> None: """ Write the nickname, using the user's color and return the number of written characters @@ -231,7 +233,7 @@ class PreMessageHelpers: buffer.addstr(nickname) @staticmethod - def write_time(buffer: 'Win', history: bool, time: datetime) -> int: + def write_time(buffer: Win, history: bool, time: datetime) -> int: """ Write the date on the yth line of the window """ diff --git a/poezio/user.py b/poezio/user.py index 5aed5031..3724d229 100644 --- a/poezio/user.py +++ b/poezio/user.py @@ -41,12 +41,12 @@ class User: deterministic=True, color='') -> None: # The oldest possible time - self.last_talked = datetime(1, 1, 1) # type: datetime + self.last_talked: datetime = datetime(1, 1, 1) self.update(affiliation, show, status, role) self.change_nick(nick) - self.jid = jid # type: JID - self.chatstate = None # type: Optional[str] - self.color = (1, 1) # type: Tuple[int, int] + self.jid: JID = jid + self.chatstate: Optional[str] = None + self.color: Tuple[int, int] = (1, 1) if color != '': self.change_color(color, deterministic) else: diff --git a/poezio/windows/base_wins.py b/poezio/windows/base_wins.py index f371c106..1347553a 100644 --- a/poezio/windows/base_wins.py +++ b/poezio/windows/base_wins.py @@ -7,7 +7,9 @@ the text window, the roster window, etc. A Tab (see the poezio.tabs module) is composed of multiple Windows """ -TAB_WIN = None # type: _CursesWindow +from __future__ import annotations + +TAB_WIN: _CursesWindow = None import logging log = logging.getLogger(__name__) @@ -41,7 +43,7 @@ class Win: __slots__ = ('_win', 'height', 'width', 'y', 'x') def __init__(self) -> None: - self._win = None # type: _CursesWindow + self._win: _CursesWindow = None self.height, self.width = 0, 0 def _resize(self, height: int, width: int, y: int, x: int) -> None: diff --git a/poezio/windows/bookmark_forms.py b/poezio/windows/bookmark_forms.py index d538e6a2..f1e737fd 100644 --- a/poezio/windows/bookmark_forms.py +++ b/poezio/windows/bookmark_forms.py @@ -161,7 +161,7 @@ class BookmarksWin(Win): self._current_input = 0 self.current_horizontal_input = 0 self._bookmarks = list(bookmarks) - self.lines = [] # type: List[Tuple[BookmarkNameInput, BookmarkJIDInput, BookmarkPasswordInput, BookmarkAutojoinWin, BookmarkMethodInput]] + self.lines: List[Tuple[BookmarkNameInput, BookmarkJIDInput, BookmarkPasswordInput, BookmarkAutojoinWin, BookmarkMethodInput]] = [] for bookmark in sorted(self._bookmarks, key=lambda x: str(x.jid)): self.lines.append((BookmarkNameInput(bookmark), BookmarkJIDInput(bookmark), diff --git a/poezio/windows/image.py b/poezio/windows/image.py index ebecb5ad..79ecf7d9 100644 --- a/poezio/windows/image.py +++ b/poezio/windows/image.py @@ -69,10 +69,10 @@ class ImageWin(Win): __slots__ = ('_image', '_display_avatar') def __init__(self) -> None: - self._image = None # type: Optional[Image.Image] + self._image: Optional[Image.Image] = None Win.__init__(self) if config.get('image_use_half_blocks'): - self._display_avatar = self._display_avatar_half_blocks # type: Callable[[int, int], None] + self._display_avatar: Callable[[int, int], None] = self._display_avatar_half_blocks else: self._display_avatar = self._display_avatar_full_blocks diff --git a/poezio/windows/info_wins.py b/poezio/windows/info_wins.py index c3975c8c..cd775e33 100644 --- a/poezio/windows/info_wins.py +++ b/poezio/windows/info_wins.py @@ -3,6 +3,8 @@ Module defining all the "info wins", ie the bar which is on top of the info buffer in normal tabs """ +from __future__ import annotations + from typing import Optional, Dict, TYPE_CHECKING, Any import logging @@ -272,9 +274,9 @@ class MucInfoWin(InfoWin): def refresh( self, - room: 'MucTab', - window: Optional['TextWin'] = None, - user: Optional['User'] = None, + room: MucTab, + window: Optional[TextWin] = None, + user: Optional[User] = None, information: Optional[Dict[str, Any]] = None ) -> None: log.debug('Refresh: %s', self.__class__.__name__) diff --git a/poezio/windows/input_placeholders.py b/poezio/windows/input_placeholders.py index 4d414636..3ec57583 100644 --- a/poezio/windows/input_placeholders.py +++ b/poezio/windows/input_placeholders.py @@ -23,7 +23,7 @@ class HelpText(Win): def __init__(self, text: str = '') -> None: Win.__init__(self) - self.txt = text # type: str + self.txt: str = text def refresh(self, txt: Optional[str] = None) -> None: log.debug('Refresh: %s', self.__class__.__name__) diff --git a/poezio/windows/inputs.py b/poezio/windows/inputs.py index 5cca8803..b3601913 100644 --- a/poezio/windows/inputs.py +++ b/poezio/windows/inputs.py @@ -41,7 +41,7 @@ class Input(Win): # it easy cut and paste text between various input def __init__(self) -> None: - self.key_func = { + self.key_func: Dict[str, Callable] = { "KEY_LEFT": self.key_left, "KEY_RIGHT": self.key_right, "KEY_END": self.key_end, @@ -66,7 +66,7 @@ class Input(Win): '^?': self.key_backspace, "M-^?": self.delete_word, # '^J': self.add_line_break, - } # type: Dict[str, Callable] + } Win.__init__(self) self.text = '' self.pos = 0 # The position of the “cursor” in the text @@ -76,8 +76,8 @@ class Input(Win): # screen self.on_input = DEFAULT_ON_INPUT # callback called on any key pressed self.color = None # use this color on addstr - self.last_completion = None # type: Optional[str] - self.hit_list = [] # type: List[str] + self.last_completion: Optional[str] = None + self.hit_list: List[str] = [] def on_delete(self) -> None: """ @@ -592,7 +592,7 @@ class HistoryInput(Input): """ __slots__ = ('help_message', 'histo_pos', 'current_completed', 'search') - history = [] # type: List[str] + history: List[str] = [] def __init__(self) -> None: Input.__init__(self) @@ -603,7 +603,7 @@ class HistoryInput(Input): self.search = False if config.get('separate_history'): # pylint: disable=assigning-non-slot - self.history = [] # type: List[str] + self.history: List[str] = [] def toggle_search(self) -> None: if self.help_message: @@ -680,7 +680,7 @@ class MessageInput(HistoryInput): Also letting the user enter colors or other text markups """ # The history is common to all MessageInput - history = [] # type: List[str] + history: List[str] = [] def __init__(self) -> None: HistoryInput.__init__(self) @@ -726,7 +726,7 @@ class CommandInput(HistoryInput): HelpMessage when a command is started The on_input callback """ - history = [] # type: List[str] + history: List[str] = [] def __init__(self, help_message: str, on_abort, on_success, on_input=None) -> None: HistoryInput.__init__(self) diff --git a/poezio/windows/list.py b/poezio/windows/list.py index c427a79e..1c5d834f 100644 --- a/poezio/windows/list.py +++ b/poezio/windows/list.py @@ -24,10 +24,10 @@ class ListWin(Win): def __init__(self, columns: Dict[str, int], with_headers: bool = True) -> None: Win.__init__(self) - self._columns = columns # type: Dict[str, int] - self._columns_sizes = {} # type: Dict[str, int] + self._columns: Dict[str, int] = columns + self._columns_sizes: Dict[str, int] = {} self.sorted_by = (None, None) # for example: ('name', '↑') - self.lines = [] # type: List[str] + self.lines: List[str] = [] self._selected_row = 0 self._starting_pos = 0 # The column number from which we start the refresh @@ -173,7 +173,7 @@ class ColumnHeaderWin(Win): def __init__(self, columns: List[str]) -> None: Win.__init__(self) self._columns = columns - self._columns_sizes = {} # type: Dict[str, int] + self._columns_sizes: Dict[str, int] = {} self._column_sel = '' self._column_order = '' self._column_order_asc = False diff --git a/poezio/windows/misc.py b/poezio/windows/misc.py index 6c04b814..8739db0c 100644 --- a/poezio/windows/misc.py +++ b/poezio/windows/misc.py @@ -37,7 +37,7 @@ class SimpleTextWin(Win): def __init__(self, text) -> None: Win.__init__(self) self._text = text - self.built_lines = [] # type: List[str] + self.built_lines: List[str] = [] def rebuild_text(self) -> None: """ diff --git a/poezio/windows/muc.py b/poezio/windows/muc.py index 951940e1..05fe683e 100644 --- a/poezio/windows/muc.py +++ b/poezio/windows/muc.py @@ -33,7 +33,7 @@ class UserList(Win): def __init__(self) -> None: Win.__init__(self) self.pos = 0 - self.cache = [] # type: List[CachedUser] + self.cache: List[CachedUser] = [] def scroll_up(self) -> bool: self.pos += self.height - 1 diff --git a/poezio/windows/roster_win.py b/poezio/windows/roster_win.py index 2efdd324..c4a1c30b 100644 --- a/poezio/windows/roster_win.py +++ b/poezio/windows/roster_win.py @@ -26,8 +26,8 @@ class RosterWin(Win): Win.__init__(self) self.pos = 0 # cursor position in the contact list self.start_pos = 1 # position of the start of the display - self.selected_row = None # type: Optional[Row] - self.roster_cache = [] # type: List[Row] + self.selected_row: Optional[Row] = None + self.roster_cache: List[Row] = [] @property def roster_len(self) -> int: diff --git a/poezio/windows/text_win.py b/poezio/windows/text_win.py index 2cb75271..ac60dee7 100644 --- a/poezio/windows/text_win.py +++ b/poezio/windows/text_win.py @@ -30,17 +30,17 @@ class TextWin(Win): Win.__init__(self) if lines_nb_limit is None: lines_nb_limit = config.get('max_lines_in_memory') - self.lines_nb_limit = lines_nb_limit # type: int + self.lines_nb_limit: int = lines_nb_limit self.pos = 0 # Each new message is built and kept here. # on resize, we rebuild all the messages - self.built_lines = [] # type: List[Union[None, Line]] + self.built_lines: List[Union[None, Line]] = [] self.lock = False - self.lock_buffer = [] # type: List[Union[None, Line]] - self.separator_after = None # type: Optional[Line] + self.lock_buffer: List[Union[None, Line]] = [] + self.separator_after: Optional[Line] = None # the Lines of the highlights in that buffer - self.highlights = [] # type: List[Line] + self.highlights: List[Line] = [] # the current HL position in that list NaN means that we’re not on # an hl. -1 is a valid position (it's before the first hl of the # list. i.e the separator, in the case where there’s no hl before diff --git a/poezio/xdg.py b/poezio/xdg.py index 0b63998c..d4ce0538 100644 --- a/poezio/xdg.py +++ b/poezio/xdg.py @@ -15,11 +15,11 @@ from os import environ from typing import Dict # $HOME has already been checked to not be None in test_env(). -DEFAULT_PATHS = { +DEFAULT_PATHS: Dict[str, Path] = { 'XDG_CONFIG_HOME': Path.home() / '.config', 'XDG_DATA_HOME': Path.home() / '.local' / 'share', 'XDG_CACHE_HOME': Path.home() / '.cache', -} # type: Dict[str, Path] +} def _get_directory(variable: str) -> Path: diff --git a/poezio/xhtml.py b/poezio/xhtml.py index 0b234c29..ebbffb02 100644 --- a/poezio/xhtml.py +++ b/poezio/xhtml.py @@ -32,7 +32,7 @@ digits = '0123456789' # never trust the modules XHTML_NS = 'http://www.w3.org/1999/xhtml' # HTML named colors -colors = { +colors: Dict[str, int] = { 'aliceblue': 231, 'antiquewhite': 231, 'aqua': 51, @@ -180,7 +180,7 @@ colors = { 'whitesmoke': 255, 'yellow': 226, 'yellowgreen': 149 -} # type: Dict[str, int] +} whitespace_re = re.compile(r'\s+') @@ -302,11 +302,11 @@ def get_hash(data: bytes) -> str: class XHTMLHandler(sax.ContentHandler): def __init__(self, force_ns=False, tmp_image_dir: Optional[Path] = None) -> None: - self.builder = [] # type: List[str] - self.formatting = [] # type: List[str] - self.attrs = [] # type: List[Dict[str, str]] - self.list_state = [] # type: List[Union[str, int]] - self.cids = {} # type: Dict[str, Optional[str]] + self.builder: List[str] = [] + self.formatting: List[str] = [] + self.attrs: List[Dict[str, str]] = [] + self.list_state: List[Union[str, int]] = [] + self.cids: Dict[str, Optional[str]] = {} self.is_pre = False self.a_start = 0 # do not care about xhtml-in namespace @@ -512,7 +512,7 @@ def convert_simple_to_full_colors(text: str) -> str: return re.sub(xhtml_simple_attr_re, add_curly_bracket, text) -number_to_color_names = { +number_to_color_names: Dict[int, str] = { 1: 'red', 2: 'green', 3: 'yellow', @@ -520,7 +520,7 @@ number_to_color_names = { 5: 'violet', 6: 'turquoise', 7: 'white' -} # type: Dict[int, str] +} def format_inline_css(_dict: Dict[str, str]) -> str: @@ -535,7 +535,7 @@ def poezio_colors_to_html(string: str) -> str: # Maintain a list of the current css attributes used # And check if a tag is open (by design, we only open # spans tag, and they cannot be nested. - current_attrs = {} # type: Dict[str, str] + current_attrs: Dict[str, str] = {} tag_open = False next_attr_char = string.find('\x19') build = ["<body xmlns='http://www.w3.org/1999/xhtml'><p>"] |