Commit 65b8046f authored by Link Mauve's avatar Link Mauve

from __future__ import annotations

Now that our baseline is Python 3.7, we can rely on type annotations to
be lazily evaluated.
parent 34ec9e3e
Pipeline #3499 passed with stages
in 5 minutes and 30 seconds
......@@ -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'
......
......@@ -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
......
......@@ -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'])
......
......@@ -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
......
......@@ -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 = ''
......
......@@ -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:
......
......@@ -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]
......
......@@ -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:
......
......@@ -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)
......
"""
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.',
......
......@@ -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()
......
......@@ -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()
......
......@@ -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():
......
......@@ -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
......
......@@ -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(
......
......@@ -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]]
}
......@@ -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\' '
......
......@@ -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__(
......
......@@ -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()
......
......@@ -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'))
......
......@@ -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,
......
......@@ -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)
......
......@@ -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)
......
......@@ -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:
......
......@@ -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.",
......
......@@ -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')
......
......@@ -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]] = {}