Unverified Commit b4d3b93d authored by mathieui's avatar mathieui

Add typing information and reformat stuff

parent 6ccf7ea7
......@@ -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'):
......
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)
"""
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
......
......@@ -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]()
......
......@@ -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]()
......
......@@ -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(
......
......@@ -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
......
......@@ -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__':
......
......@@ -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
"""
......
......@@ -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
......
......@@ -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:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment