summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--poezio/bookmarks.py23
-rw-r--r--poezio/colors.py22
-rw-r--r--poezio/decorators.py43
-rw-r--r--poezio/tabs/confirmtab.py6
-rw-r--r--poezio/tabs/listtab.py6
-rw-r--r--poezio/tabs/muctab.py65
-rw-r--r--poezio/tabs/rostertab.py6
-rwxr-xr-xpoezio/theming.py6
-rw-r--r--poezio/windows/base_wins.py10
-rw-r--r--poezio/windows/funcs.py17
-rw-r--r--poezio/windows/info_bar.py9
11 files changed, 109 insertions, 104 deletions
diff --git a/poezio/bookmarks.py b/poezio/bookmarks.py
index f6f22363..0406de94 100644
--- a/poezio/bookmarks.py
+++ b/poezio/bookmarks.py
@@ -30,7 +30,7 @@ Adding a remote bookmark:
import functools
import logging
-from typing import Optional, List
+from typing import Optional, List, Union
from slixmpp import JID
from slixmpp.plugins.xep_0048 import Bookmarks, Conference, URL
@@ -130,7 +130,7 @@ class Bookmark:
class BookmarkList:
def __init__(self):
- self.bookmarks = []
+ self.bookmarks = [] # type: List[Bookmark]
preferred = config.get('use_bookmarks_method').lower()
if preferred not in ('pep', 'privatexml'):
preferred = 'privatexml'
@@ -140,15 +140,16 @@ class BookmarkList:
'pep': False,
}
- def __getitem__(self, key):
+ def __getitem__(self, key: Union[str, JID, int]) -> Optional[Bookmark]:
if isinstance(key, (str, JID)):
for i in self.bookmarks:
if key == i.jid:
return i
- else:
+ elif isinstance(key, int):
return self.bookmarks[key]
+ return None
- def __in__(self, key):
+ def __in__(self, key) -> bool:
if isinstance(key, (str, JID)):
for bookmark in self.bookmarks:
if bookmark.jid == key:
@@ -168,16 +169,16 @@ class BookmarkList:
def __iter__(self):
return iter(self.bookmarks)
- def local(self):
+ def local(self) -> List[Bookmark]:
return [bm for bm in self.bookmarks if bm.method == 'local']
- def remote(self):
+ def remote(self) -> List[Bookmark]:
return [bm for bm in self.bookmarks if bm.method == 'remote']
- def set(self, new):
+ def set(self, new: List[Bookmark]):
self.bookmarks = new
- def append(self, bookmark):
+ def append(self, bookmark: Bookmark):
bookmark_exists = self[bookmark.jid]
if not bookmark_exists:
self.bookmarks.append(bookmark)
@@ -185,7 +186,7 @@ class BookmarkList:
self.bookmarks.remove(bookmark_exists)
self.bookmarks.append(bookmark)
- def set_bookmarks_method(self, value):
+ def set_bookmarks_method(self, value: str):
if self.available_storage.get(value):
self.preferred = value
config.set_and_save('use_bookmarks_method', value)
@@ -306,7 +307,7 @@ class BookmarkList:
self.append(b)
-def stanza_storage(bookmarks):
+def stanza_storage(bookmarks: BookmarkList) -> Bookmarks:
"""Generate a <storage/> stanza with the conference elements."""
storage = Bookmarks()
for b in (b for b in bookmarks if b.method == 'remote'):
diff --git a/poezio/colors.py b/poezio/colors.py
index 2e90b9b0..6bbbb12e 100644
--- a/poezio/colors.py
+++ b/poezio/colors.py
@@ -1,14 +1,17 @@
+from typing import Tuple, Dict, List
import curses
import hashlib
import math
+Palette = Dict[float, int]
+
# BT.601 (YCbCr) constants, see XEP-0392
K_R = 0.299
K_G = 0.587
K_B = 1 - K_R - K_G
-def ncurses_color_to_rgb(color):
+def ncurses_color_to_rgb(color: int) -> Tuple[float, float, float]:
if color <= 15:
try:
(r, g, b) = curses.color_content(color)
@@ -30,15 +33,16 @@ def ncurses_color_to_rgb(color):
return r / 5, g / 5, b / 5
-def rgb_to_ycbcr(r, g, b):
+def rgb_to_ycbcr(r: float, g: float, b: float) -> Tuple[float, float, float]:
y = K_R * r + K_G * g + K_B * b
cr = (r - y) / (1 - K_R) / 2
cb = (b - y) / (1 - K_B) / 2
return y, cb, cr
-def generate_ccg_palette(curses_palette, reference_y):
- cbcr_palette = {}
+def generate_ccg_palette(curses_palette: List[int],
+ reference_y: float) -> Palette:
+ cbcr_palette = {} # type: Dict[float, Tuple[float, int]]
for curses_color in curses_palette:
r, g, b = ncurses_color_to_rgb(curses_color)
# drop grayscale
@@ -60,14 +64,14 @@ def generate_ccg_palette(curses_palette, reference_y):
}
-def text_to_angle(text):
+def text_to_angle(text: str) -> float:
hf = hashlib.sha1()
hf.update(text.encode("utf-8"))
hue = int.from_bytes(hf.digest()[:2], "little")
return hue / 65535 * math.pi * 2
-def angle_to_cbcr_edge(angle):
+def angle_to_cbcr_edge(angle: float) -> Tuple[float, float]:
cr = math.sin(angle)
cb = math.cos(angle)
if abs(cr) > abs(cb):
@@ -77,7 +81,7 @@ def angle_to_cbcr_edge(angle):
return cb * factor, cr * factor
-def cbcr_to_angle(cb, cr):
+def cbcr_to_angle(cb: float, cr: float) -> float:
magn = math.sqrt(cb**2 + cr**2)
if magn > 0:
cr /= magn
@@ -85,7 +89,7 @@ def cbcr_to_angle(cb, cr):
return math.atan2(cr, cb) % (2 * math.pi)
-def ccg_palette_lookup(palette, angle):
+def ccg_palette_lookup(palette: Palette, angle: float) -> int:
# try quick lookup first
try:
color = palette[round(angle, 2)]
@@ -105,6 +109,6 @@ def ccg_palette_lookup(palette, angle):
return best
-def ccg_text_to_color(palette, text):
+def ccg_text_to_color(palette, text: str) -> int:
angle = text_to_angle(text)
return ccg_palette_lookup(palette, angle)
diff --git a/poezio/decorators.py b/poezio/decorators.py
index 7823dbaf..bf1c2ebe 100644
--- a/poezio/decorators.py
+++ b/poezio/decorators.py
@@ -1,6 +1,7 @@
"""
Module containing various decorators
"""
+from typing import Any, Callable, List, Optional
from poezio import common
@@ -9,7 +10,7 @@ class RefreshWrapper:
def __init__(self):
self.core = None
- def conditional(self, func):
+ def conditional(self, func: Callable) -> Callable:
"""
Decorator to refresh the UI if the wrapped function
returns True
@@ -23,7 +24,7 @@ class RefreshWrapper:
return wrap
- def always(self, func):
+ def always(self, func: Callable) -> Callable:
"""
Decorator that refreshs the UI no matter what after the function
"""
@@ -36,7 +37,7 @@ class RefreshWrapper:
return wrap
- def update(self, func):
+ def update(self, func: Callable) -> Callable:
"""
Decorator that only updates the screen
"""
@@ -60,7 +61,7 @@ class CommandArgParser:
"""
@staticmethod
- def raw(func):
+ def raw(func: Callable) -> Callable:
"""Just call the function with a single string, which is the original string
untouched
"""
@@ -71,7 +72,7 @@ class CommandArgParser:
return wrap
@staticmethod
- def ignored(func):
+ def ignored(func: Callable) -> Callable:
"""
Call the function without any argument
"""
@@ -82,9 +83,9 @@ class CommandArgParser:
return wrap
@staticmethod
- def quoted(mandatory,
+ def quoted(mandatory: int,
optional=0,
- defaults=None,
+ defaults: Optional[List[Any]] = None,
ignore_trailing_arguments=False):
"""The function receives a list with a number of arguments that is between
the numbers `mandatory` and `optional`.
@@ -128,31 +129,31 @@ class CommandArgParser:
['un et demi', 'deux', 'trois quatre cinq six']
"""
- if defaults is None:
- defaults = []
+ default_args_outer = defaults or []
- def first(func):
- def second(self, args, *a, **kw):
- default_args = defaults
+ def first(func: Callable):
+ def second(self, args: str, *a, **kw):
+ default_args = default_args_outer
if args and args.strip():
- args = common.shell_split(args)
+ split_args = common.shell_split(args)
else:
- args = []
- if len(args) < mandatory:
+ split_args = []
+ if len(split_args) < mandatory:
return func(self, None, *a, **kw)
- res, args = args[:mandatory], args[mandatory:]
+ res, split_args = split_args[:mandatory], split_args[
+ mandatory:]
if optional == -1:
- opt_args = args[:]
+ opt_args = split_args[:]
else:
- opt_args = args[:optional]
+ opt_args = split_args[:optional]
if opt_args:
res += opt_args
- args = args[len(opt_args):]
+ split_args = split_args[len(opt_args):]
default_args = default_args[len(opt_args):]
res += default_args
- if args and res and not ignore_trailing_arguments:
- res[-1] += " " + " ".join(args)
+ if split_args and res and not ignore_trailing_arguments:
+ res[-1] += " " + " ".join(split_args)
return func(self, res, *a, **kw)
return second
diff --git a/poezio/tabs/confirmtab.py b/poezio/tabs/confirmtab.py
index c76883dd..c13de4a6 100644
--- a/poezio/tabs/confirmtab.py
+++ b/poezio/tabs/confirmtab.py
@@ -99,10 +99,8 @@ class ConfirmTab(Tab):
def on_input(self, key, raw):
res = self.input.do_command(key, raw=raw)
- if res and not isinstance(self.input, windows.Input):
- return True
- elif res:
- return False
+ if res:
+ return not isinstance(self.input, windows.Input)
if not raw and key in self.key_func:
return self.key_func[key]()
diff --git a/poezio/tabs/listtab.py b/poezio/tabs/listtab.py
index 6a4da08e..07b3fe05 100644
--- a/poezio/tabs/listtab.py
+++ b/poezio/tabs/listtab.py
@@ -161,10 +161,8 @@ class ListTab(Tab):
def on_input(self, key, raw):
res = self.input.do_command(key, raw=raw)
- if res and not isinstance(self.input, windows.Input):
- return True
- elif res:
- return False
+ if res:
+ return not isinstance(self.input, windows.Input)
if not raw and key in self.key_func:
return self.key_func[key]()
diff --git a/poezio/tabs/muctab.py b/poezio/tabs/muctab.py
index 934dc0b1..507a47bd 100644
--- a/poezio/tabs/muctab.py
+++ b/poezio/tabs/muctab.py
@@ -14,8 +14,9 @@ import os
import random
import re
from datetime import datetime
-from typing import Dict, Callable
+from typing import Dict, Callable, List, Optional, Union, Set
+from slixmpp import JID
from poezio.tabs import ChatTab, Tab, SHOW_NAME
from poezio import common
@@ -56,15 +57,15 @@ class MucTab(ChatTab):
# our nick in the MUC
self.own_nick = nick
# self User object
- self.own_user = None
+ self.own_user = None # type: Optional[User]
self.name = jid
self.password = password
# buffered presences
self.presence_buffer = []
# userlist
- self.users = []
+ self.users = [] # type: List[User]
# private conversations
- self.privates = []
+ self.privates = [] # type: List[Tab]
self.topic = ''
self.topic_from = ''
# Self ping event, so we can cancel it when we leave the room
@@ -78,7 +79,7 @@ class MucTab(ChatTab):
self.info_header = windows.MucInfoWin()
self.input = windows.MessageInput()
# List of ignored users
- self.ignores = []
+ self.ignores = [] # type: List[User]
# keys
self.register_keys()
self.update_keys()
@@ -91,12 +92,12 @@ class MucTab(ChatTab):
def general_jid(self):
return self.name
- def check_send_chat_state(self):
+ def check_send_chat_state(self) -> bool:
"If we should send a chat state"
return self.joined
@property
- def last_connection(self):
+ def last_connection(self) -> Optional[datetime]:
last_message = self._text_buffer.last_message
if last_message:
return last_message.time
@@ -135,7 +136,7 @@ class MucTab(ChatTab):
show=status.show,
seconds=seconds)
- def leave_room(self, message):
+ def leave_room(self, message: str):
if self.joined:
info_col = dump_tuple(get_theme().COLOR_INFORMATION_TEXT)
char_quit = get_theme().CHAR_QUIT
@@ -145,7 +146,7 @@ class MucTab(ChatTab):
self.general_jid):
color = dump_tuple(get_theme().COLOR_OWN_NICK)
else:
- color = 3
+ color = "3"
if message:
msg = ('\x19%(color_spec)s}%(spec)s\x19%(info_col)s} '
@@ -179,7 +180,10 @@ class MucTab(ChatTab):
muc.leave_groupchat(self.core.xmpp, self.name, self.own_nick,
message)
- def change_affiliation(self, nick_or_jid, affiliation, reason=''):
+ def change_affiliation(self,
+ nick_or_jid: Union[str, JID],
+ affiliation: str,
+ reason=''):
"""
Change the affiliation of a nick or JID
"""
@@ -215,7 +219,7 @@ class MucTab(ChatTab):
callback=callback,
reason=reason)
- def change_role(self, nick, role, reason=''):
+ def change_role(self, nick: str, role: str, reason=''):
"""
Change the role of a nick
"""
@@ -238,7 +242,7 @@ class MucTab(ChatTab):
self.core.xmpp, self.name, nick, reason, role, callback=callback)
@refresh_wrapper.conditional
- def print_info(self, nick):
+ def print_info(self, nick: str) -> bool:
"""Print information about a user"""
user = self.get_user_by_name(nick)
if not user:
@@ -269,7 +273,7 @@ class MucTab(ChatTab):
self.add_message(info, typ=0)
return True
- def change_topic(self, topic):
+ def change_topic(self, topic: str):
"""Change the current topic"""
muc.change_subject(self.core.xmpp, self.name, topic)
@@ -331,7 +335,7 @@ class MucTab(ChatTab):
self.text_win.rebuild_everything(self._text_buffer)
@refresh_wrapper.conditional
- def set_nick_color(self, nick, color):
+ def set_nick_color(self, nick: str, color: str) -> bool:
"Set a custom color for a nick, permanently"
user = self.get_user_by_name(nick)
if color not in xhtml.colors and color not in ('unset', 'random'):
@@ -374,7 +378,7 @@ class MucTab(ChatTab):
self.send_composing_chat_state(empty_after)
return False
- def get_nick(self):
+ def get_nick(self) -> str:
if config.get('show_muc_jid'):
return self.name
bookmark = self.core.bookmarks[self.name]
@@ -479,7 +483,7 @@ class MucTab(ChatTab):
status_codes.add(status_code.attrib['code'])
self.own_join(from_nick, new_user, status_codes)
- def own_join(self, from_nick, new_user, status_codes):
+ def own_join(self, from_nick: str, new_user: User, status_codes: Set[str]):
"""
Handle the last presence we received, entering the room
"""
@@ -500,7 +504,7 @@ class MucTab(ChatTab):
self.general_jid):
color = dump_tuple(new_user.color)
else:
- color = 3
+ color = "3"
info_col = dump_tuple(get_theme().COLOR_INFORMATION_TEXT)
warn_col = dump_tuple(get_theme().COLOR_WARNING_TEXT)
@@ -848,11 +852,11 @@ class MucTab(ChatTab):
self.add_message(kick_msg, typ=2)
def on_user_leave_groupchat(self,
- user,
- jid,
- status,
- from_nick,
- from_room,
+ user: User,
+ jid: JID,
+ status: str,
+ from_nick: str,
+ from_room: JID,
server_initiated=False):
"""
When an user leaves a groupchat
@@ -960,17 +964,12 @@ class MucTab(ChatTab):
self.general_jid)
if hide_status_change < -1:
hide_status_change = -1
- if ((hide_status_change == -1 or \
- user.has_talked_since(hide_status_change) or\
- user.nick == self.own_nick)\
- and\
- (affiliation != user.affiliation or\
- role != user.role or\
- show != user.show or\
- status != user.status))\
- or\
- (affiliation != user.affiliation or\
- role != user.role):
+ if ((hide_status_change == -1
+ or user.has_talked_since(hide_status_change)
+ or user.nick == self.own_nick) and
+ (affiliation != user.affiliation or role != user.role
+ or show != user.show or status != user.status)) or (
+ affiliation != user.affiliation or role != user.role):
# display the message in the room
self._text_buffer.add_message(msg)
self.core.on_user_changed_status_in_private(
diff --git a/poezio/tabs/rostertab.py b/poezio/tabs/rostertab.py
index 11473e83..9f609f61 100644
--- a/poezio/tabs/rostertab.py
+++ b/poezio/tabs/rostertab.py
@@ -1114,10 +1114,8 @@ class RosterInfoTab(Tab):
if key == '^M':
selected_row = self.roster_win.get_selected_row()
res = self.input.do_command(key, raw=raw)
- if res and not isinstance(self.input, windows.Input):
- return True
- elif res:
- return False
+ if res:
+ return not isinstance(self.input, windows.Input)
if key == '^M':
self.core.on_roster_enter_key(selected_row)
return selected_row
diff --git a/poezio/theming.py b/poezio/theming.py
index 6491e03c..db1ccb39 100755
--- a/poezio/theming.py
+++ b/poezio/theming.py
@@ -281,7 +281,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
+ CCG_PALETTE = None # type: Optional[Dict[float, int]]
CCG_Y = 0.5**0.45
# yapf: enable
@@ -566,8 +566,8 @@ def reload_theme() -> Optional[str]:
if hasattr(new_theme, 'theme'):
theme = new_theme.theme
prepare_ccolor_palette(theme)
- else:
- return 'No theme present in the theme file'
+ return None
+ return 'No theme present in the theme file'
if __name__ == '__main__':
diff --git a/poezio/windows/base_wins.py b/poezio/windows/base_wins.py
index eaedd82b..89c4b73c 100644
--- a/poezio/windows/base_wins.py
+++ b/poezio/windows/base_wins.py
@@ -15,6 +15,8 @@ log = logging.getLogger(__name__)
import curses
import string
+from typing import Optional, Tuple
+
from poezio.theming import to_curses_attr, read_tuple
FORMAT_CHAR = '\x19'
@@ -51,7 +53,7 @@ class Win:
if self._win is None:
self._win = DummyWin()
- def resize(self, height, width, y, x):
+ def resize(self, height: int, width: int, y: int, x: int):
"""
Override if something has to be done on resize
"""
@@ -81,13 +83,13 @@ class Win:
except:
pass
- def move(self, y, x):
+ def move(self, y: int, x: int):
try:
self._win.move(y, x)
except:
pass
- def addstr_colored(self, text, y=None, x=None):
+ def addstr_colored(self, text: str, y=None, x=None):
"""
Write a string on the window, setting the
attributes as they are in the string.
@@ -146,7 +148,7 @@ class Win:
next_attr_char = text.find(FORMAT_CHAR)
self.addstr(text)
- def finish_line(self, color=None):
+ def finish_line(self, color: Optional[Tuple] = None):
"""
Write colored spaces until the end of line
"""
diff --git a/poezio/windows/funcs.py b/poezio/windows/funcs.py
index 3648bac3..d118f353 100644
--- a/poezio/windows/funcs.py
+++ b/poezio/windows/funcs.py
@@ -3,16 +3,17 @@ Standalone functions used by the modules
"""
import string
-DIGITS = string.digits + '-'
-
+from typing import Optional, List
from poezio.windows.base_wins import FORMAT_CHAR, format_chars
+DIGITS = string.digits + '-'
+
-def find_first_format_char(text, chars=None):
- if chars is None:
- chars = format_chars
+def find_first_format_char(text: str,
+ chars: Optional[List[str]] = None) -> int:
+ to_find = chars or format_chars
pos = -1
- for char in chars:
+ for char in to_find:
p = text.find(char)
if p == -1:
continue
@@ -21,7 +22,7 @@ def find_first_format_char(text, chars=None):
return pos
-def truncate_nick(nick, size=10):
+def truncate_nick(nick: str, size=10) -> str:
if size < 1:
size = 1
if nick and len(nick) > size:
@@ -29,7 +30,7 @@ def truncate_nick(nick, size=10):
return nick
-def parse_attrs(text, previous=None):
+def parse_attrs(text: str, previous: Optional[List[str]] = None) -> List[str]:
next_attr_char = text.find(FORMAT_CHAR)
if previous:
attrs = previous
diff --git a/poezio/windows/info_bar.py b/poezio/windows/info_bar.py
index 6e338a78..f4ba1f1f 100644
--- a/poezio/windows/info_bar.py
+++ b/poezio/windows/info_bar.py
@@ -32,7 +32,8 @@ class GlobalInfoBar(Win):
show_inactive = config.get('show_inactive_tabs')
for nb, tab in enumerate(self.core.tabs):
- if not tab: continue
+ if not tab:
+ continue
color = tab.color
if not show_inactive and color is get_theme().COLOR_TAB_NORMAL:
continue
@@ -72,8 +73,10 @@ class VerticalGlobalInfoBar(Win):
self._win.erase()
sorted_tabs = [tab for tab in self.core.tabs if tab]
if not config.get('show_inactive_tabs'):
- sorted_tabs = [tab for tab in sorted_tabs if\
- tab.vertical_color != get_theme().COLOR_VERTICAL_TAB_NORMAL]
+ sorted_tabs = [
+ tab for tab in sorted_tabs
+ if tab.vertical_color != get_theme().COLOR_VERTICAL_TAB_NORMAL
+ ]
nb_tabs = len(sorted_tabs)
use_nicks = config.get('use_tab_nicks')
if nb_tabs >= height: