Commit 53633a5c authored by mathieui's avatar mathieui

refactor: rewrite config.get() to getbool, getstr, getint…

parent b2fbb313
......@@ -163,7 +163,7 @@ class Bookmark:
class BookmarkList:
def __init__(self):
self.bookmarks: List[Bookmark] = []
preferred = config.get('use_bookmarks_method').lower()
preferred = config.getstr('use_bookmarks_method').lower()
if preferred not in ('pep', 'privatexml'):
preferred = 'privatexml'
self.preferred = preferred
......@@ -244,7 +244,7 @@ class BookmarkList:
async def save(self, xmpp: ClientXMPP, core=None):
"""Save all the bookmarks."""
self.save_local()
if config.get('use_remote_bookmarks'):
if config.getbool('use_remote_bookmarks'):
try:
result = await self.save_remote(xmpp)
if core is not None:
......@@ -292,10 +292,9 @@ class BookmarkList:
def get_local(self):
"""Add the locally stored bookmarks to the list."""
rooms = config.get('rooms')
rooms = config.getlist('rooms')
if not rooms:
return
rooms = rooms.split(':')
for room in rooms:
try:
jid = JID(room)
......
......@@ -19,7 +19,7 @@ import pkg_resources
from configparser import RawConfigParser, NoOptionError, NoSectionError
from pathlib import Path
from shutil import copy2
from typing import Callable, Dict, List, Optional, Union, Tuple
from typing import Callable, Dict, List, Optional, Union, Tuple, cast
from poezio.args import parse_args
from poezio import xdg
......@@ -208,13 +208,13 @@ class Config:
try:
if isinstance(default, bool):
res = self.getboolean(option, section)
res = self.configparser.getboolean(section, option)
elif isinstance(default, int):
res = self.getint(option, section)
res = self.configparser.getint(section, option)
elif isinstance(default, float):
res = self.getfloat(option, section)
res = self.configparser.getfloat(section, option)
else:
res = self.getstr(option, section)
res = self.configparser.get(section, option)
except (NoOptionError, NoSectionError, ValueError, AttributeError):
return default if default is not None else ''
......@@ -222,6 +222,12 @@ class Config:
return default
return res
def _get_default(self, option, section):
if self.default:
return self.default.get(section, {}).get(option)
else:
return ''
def sections(self, *args, **kwargs):
return self.configparser.sections(*args, **kwargs)
......@@ -287,29 +293,45 @@ class Config:
"""
return conv(self.__get(option, section, **kwargs))
def getstr(self, option, section=DEFSECTION):
def getstr(self, option, section=DEFSECTION) -> str:
"""
get a value and returns it as a string
"""
return self.__get(option, section)
try:
return self.configparser.get(section, option)
except (NoOptionError, NoSectionError, ValueError, AttributeError):
return cast(str, self._get_default(option, section))
def getint(self, option, section=DEFSECTION):
def getint(self, option, section=DEFSECTION) -> int:
"""
get a value and returns it as an int
"""
return self.configparser.getint(section, option)
try:
return self.configparser.getint(section, option)
except (NoOptionError, NoSectionError, ValueError, AttributeError):
return cast(int, self._get_default(option, section))
def getfloat(self, option, section=DEFSECTION):
def getfloat(self, option, section=DEFSECTION) -> float:
"""
get a value and returns it as a float
"""
return self.configparser.getfloat(section, option)
try:
return self.configparser.getfloat(section, option)
except (NoOptionError, NoSectionError, ValueError, AttributeError):
return cast(float, self._get_default(option, section))
def getboolean(self, option, section=DEFSECTION):
def getbool(self, option, section=DEFSECTION) -> bool:
"""
get a value and returns it as a boolean
"""
return self.configparser.getboolean(section, option)
try:
return self.configparser.getboolean(section, option)
except (NoOptionError, NoSectionError, ValueError, AttributeError):
return cast(bool, self._get_default(option, section))
def getlist(self, option, section=DEFSECTION) -> List[str]:
return self.getstr(option, section).split(':')
def write_in_file(self, section: str, option: str,
value: ConfigValue) -> bool:
......@@ -450,8 +472,8 @@ class Config:
# Special case for a 'toggle' value. We take the current value
# and set the opposite. Warning if the no current value exists
# or it is not a bool.
if value == "toggle":
current = self.get(option, "", section)
if isinstance(value, str) and value == "toggle":
current = self.getbool(option, section)
if isinstance(current, bool):
value = str(not current)
else:
......@@ -464,6 +486,7 @@ class Config:
'Could not toggle option: %s.'
' Current value is %s.' % (option, current or "empty"),
'Warning')
value = str(value)
if self.has_section(section):
self.configparser.set(section, option, value)
else:
......
......@@ -38,24 +38,24 @@ class Connection(slixmpp.ClientXMPP):
__init = False
def __init__(self):
keyfile = config.get('keyfile')
certfile = config.get('certfile')
keyfile = config.getstr('keyfile')
certfile = config.getstr('certfile')
device_id = config.get('device_id')
device_id = config.getstr('device_id')
if not device_id:
rng = random.SystemRandom()
device_id = base64.urlsafe_b64encode(
rng.getrandbits(24).to_bytes(3, 'little')).decode('ascii')
config.set_and_save('device_id', device_id)
if config.get('jid'):
if config.getstr('jid'):
# Field used to know if we are anonymous or not.
# many features will be handled differently
# depending on this setting
self.anon = False
jid = config.get('jid')
password = config.get('password')
eval_password = config.get('eval_password')
jid = config.getstr('jid')
password = config.getstr('password')
eval_password = config.getstr('eval_password')
if not password and not eval_password and not (keyfile
and certfile):
password = getpass.getpass()
......@@ -79,7 +79,7 @@ class Connection(slixmpp.ClientXMPP):
'\n')
else: # anonymous auth
self.anon = True
jid = config.get('server')
jid = config.getstr('server')
password = None
try:
jid = JID(jid)
......@@ -91,17 +91,17 @@ class Connection(slixmpp.ClientXMPP):
device_id) if jid.resource else 'poezio-%s' % device_id
# TODO: use the system language
slixmpp.ClientXMPP.__init__(
self, jid, password, lang=config.get('lang'))
self, jid, password, lang=config.getstr('lang'))
force_encryption = config.get('force_encryption')
force_encryption = config.getbool('force_encryption')
if force_encryption:
self['feature_mechanisms'].unencrypted_plain = False
self['feature_mechanisms'].unencrypted_digest = False
self['feature_mechanisms'].unencrypted_cram = False
self['feature_mechanisms'].unencrypted_scram = False
self.keyfile = config.get('keyfile')
self.certfile = config.get('certfile')
self.keyfile = keyfile
self.certfile = certfile
if keyfile and not certfile:
log.error(
'keyfile is present in configuration file without certfile')
......@@ -110,15 +110,15 @@ class Connection(slixmpp.ClientXMPP):
'certfile is present in configuration file without keyfile')
self.core = None
self.auto_reconnect = config.get('auto_reconnect')
self.auto_reconnect = config.getbool('auto_reconnect')
self.auto_authorize = None
# prosody defaults, lowest is AES128-SHA, it should be a minimum
# for anything that came out after 2002
self.ciphers = config.get(
self.ciphers = config.getstr(
'ciphers', 'HIGH+kEDH:HIGH+kEECDH:HIGH:!PSK'
':!SRP:!3DES:!aNULL')
self.ca_certs = config.get('ca_cert_path') or None
interval = config.get('whitespace_interval')
self.ca_certs = config.getstr('ca_cert_path') or None
interval = config.getint('whitespace_interval')
if int(interval) > 0:
self.whitespace_keepalive_interval = int(interval)
else:
......@@ -156,21 +156,21 @@ class Connection(slixmpp.ClientXMPP):
# without a body
XEP_0184._filter_add_receipt_request = fixes._filter_add_receipt_request
self.register_plugin('xep_0184')
self.plugin['xep_0184'].auto_ack = config.get('ack_message_receipts')
self.plugin['xep_0184'].auto_request = config.get(
self.plugin['xep_0184'].auto_ack = config.getbool('ack_message_receipts')
self.plugin['xep_0184'].auto_request = config.getbool(
'request_message_receipts')
self.register_plugin('xep_0191')
if config.get('enable_smacks'):
if config.getbool('enable_smacks'):
self.register_plugin('xep_0198')
self.register_plugin('xep_0199')
if config.get('enable_user_nick'):
if config.getbool('enable_user_nick'):
self.register_plugin('xep_0172')
if config.get('send_poezio_info'):
if config.getbool('send_poezio_info'):
info = {'name': 'poezio', 'version': options.custom_version}
if config.get('send_os_info'):
if config.getbool('send_os_info'):
info['os'] = common.get_os_info()
self.plugin['xep_0030'].set_identities(identities={('client',
'console',
......@@ -182,7 +182,7 @@ class Connection(slixmpp.ClientXMPP):
'console',
None, '')})
self.register_plugin('xep_0092', pconfig=info)
if config.get('send_time'):
if config.getbool('send_time'):
self.register_plugin('xep_0202')
self.register_plugin('xep_0224')
self.register_plugin('xep_0231')
......@@ -216,8 +216,8 @@ class Connection(slixmpp.ClientXMPP):
# Happens when we change the value with /set while we are not
# connected. Do nothing in that case
return
ping_interval = config.get('connection_check_interval')
timeout_delay = config.get('connection_timeout_delay')
ping_interval = config.getint('connection_check_interval')
timeout_delay = config.getint('connection_timeout_delay')
if timeout_delay <= 0:
# We help the stupid user (with a delay of 0, poezio will try to
# reconnect immediately because the timeout is immediately
......@@ -234,7 +234,7 @@ class Connection(slixmpp.ClientXMPP):
"""
Connect and process events.
"""
custom_host = config.get('custom_host')
custom_host = config.getstr('custom_host')
custom_port = config.get('custom_port', 5222)
if custom_port == -1:
custom_port = 5222
......
......@@ -424,8 +424,8 @@ class CommandCore:
tab.password = password
tab.join()
if config.get('synchronise_open_rooms') and room not in self.core.bookmarks:
method = 'remote' if config.get(
if config.getbool('synchronise_open_rooms') and room not in self.core.bookmarks:
method = 'remote' if config.getbool(
'use_remote_bookmarks') else 'local'
await self._add_bookmark(
room=room,
......@@ -472,7 +472,7 @@ class CommandCore:
room, nick = self._parse_join_jid(args[0] if args else '')
password = args[2] if len(args) > 2 else None
method = 'remote' if config.get('use_remote_bookmarks') else 'local'
method = 'remote' if config.getbool('use_remote_bookmarks') else 'local'
autojoin = (method == 'local' or
(len(args) > 1 and args[1].lower() == 'true'))
......
......@@ -82,7 +82,7 @@ class CompletionCore:
def theme(self, the_input):
""" Completion for /theme"""
themes_dir = config.get('themes_dir')
themes_dir = config.getstr('themes_dir')
themes_dir = Path(themes_dir).expanduser(
) if themes_dir else xdg.DATA_HOME / 'themes'
try:
......@@ -220,7 +220,7 @@ class CompletionCore:
nicks = [tab.own_nick] if tab else []
default = os.environ.get('USER') if os.environ.get(
'USER') else 'poezio'
nick = config.get('default_nick')
nick = config.getstr('default_nick')
if not nick:
if default not in nicks:
nicks.append(default)
......@@ -436,7 +436,7 @@ class CompletionCore:
nicks = [tab.own_nick] if tab else []
default = os.environ.get('USER') if os.environ.get(
'USER') else 'poezio'
nick = config.get('default_nick')
nick = config.getstr('default_nick')
if not nick:
if default not in nicks:
nicks.append(default)
......
......@@ -95,9 +95,9 @@ class Core:
self.connection_time = time.time()
self.last_stream_error = None
self.stdscr = None
status = config.get('status')
status = config.getstr('status')
status = POSSIBLE_SHOW.get(status, None)
self.status = Status(show=status, message=config.get('status_message'))
self.status = Status(show=status, message=config.getstr('status_message'))
self.running = True
self.xmpp = connection.Connection()
self.xmpp.core = self
......@@ -115,7 +115,7 @@ class Core:
self.information_buffer = TextBuffer()
self.information_win_size = cast(
int,
config.get('info_win_height', section='var'),
config.getint('info_win_height', section='var'),
)
self.information_win = windows.TextWin(300)
self.information_buffer.add_window(self.information_win)
......@@ -134,10 +134,10 @@ class Core:
self.tabs = Tabs(self.events)
self.previous_tab_nb = 0
own_nick = config.get('default_nick')
own_nick = config.getstr('default_nick')
own_nick = own_nick or self.xmpp.boundjid.user
own_nick = own_nick or os.environ.get('USER')
own_nick = own_nick or 'poezio'
own_nick = own_nick or 'poezio_user'
self.own_nick = own_nick
self.size = SizeManager(self)
......@@ -292,12 +292,12 @@ class Core:
for name, handler in xmpp_event_handlers:
self.xmpp.add_event_handler(name, handler)
if config.get('enable_avatars'):
if config.getbool('enable_avatars'):
self.xmpp.add_event_handler("vcard_avatar_update",
self.handler.on_vcard_avatar)
self.xmpp.add_event_handler("avatar_metadata_publish",
self.handler.on_0084_avatar)
if config.get('enable_user_nick'):
if config.getbool('enable_user_nick'):
self.xmpp.add_event_handler("user_nick_publish",
self.handler.on_nick_received)
all_stanzas = Callback('custom matcher', connection.MatchAll(None),
......@@ -513,7 +513,7 @@ class Core:
"""
Load the plugins on startup.
"""
plugins = config.get('plugins_autoload')
plugins = config.getstr('plugins_autoload')
if ':' in plugins:
for plugin in plugins.split(':'):
self.plugin_manager.load(plugin, unload_first=False)
......@@ -609,7 +609,7 @@ class Core:
except ValueError:
pass
else:
if self.tabs.current_tab.nb == nb and config.get(
if self.tabs.current_tab.nb == nb and config.getbool(
'go_to_previous_tab_on_alt_number'):
self.go_to_previous_tab()
else:
......@@ -722,9 +722,9 @@ class Core:
work. If you try to do anything else, your |, [, <<, etc will be
interpreted as normal command arguments, not shell special tokens.
"""
if config.get('exec_remote'):
if config.getbool('exec_remote'):
# We just write the command in the fifo
fifo_path = config.get('remote_fifo_path')
fifo_path = config.getstr('remote_fifo_path')
filename = os.path.join(fifo_path, 'poezio.fifo')
if not self.remote_fifo:
try:
......@@ -818,7 +818,7 @@ class Core:
or to use it when joining a new muc)
"""
self.status = Status(show=pres, message=msg)
if config.get('save_status'):
if config.getbool('save_status'):
ok = config.silent_set('status', pres if pres else '')
msg = msg.replace('\n', '|') if msg else ''
ok = ok and config.silent_set('status_message', msg)
......@@ -1040,7 +1040,7 @@ class Core:
returns False if it could not move the tab, True otherwise
"""
return self.tabs.insert_tab(old_pos, new_pos,
config.get('create_gaps'))
config.getbool('create_gaps'))
### Move actions (e.g. go to next room) ###
......@@ -1308,7 +1308,7 @@ class Core:
tab.on_close()
del tab.key_func # Remove self references
del tab.commands # and make the object collectable
self.tabs.delete(tab, gap=config.get('create_gaps'))
self.tabs.delete(tab, gap=config.getbool('create_gaps'))
logger.close(tab.name)
if was_current:
self.tabs.current_tab.on_gain_focus()
......@@ -1342,13 +1342,13 @@ class Core:
"""
Displays an informational message in the "Info" buffer
"""
filter_types = config.get('information_buffer_type_filter').split(':')
filter_types = config.getlist('information_buffer_type_filter')
if typ.lower() in filter_types:
log.debug(
'Did not show the message:\n\t%s> %s \n\tdue to '
'information_buffer_type_filter configuration', typ, msg)
return False
filter_messages = config.get('filter_info_messages').split(':')
filter_messages = config.getlist('filter_info_messages')
for words in filter_messages:
if words and words in msg:
log.debug(
......@@ -1364,11 +1364,11 @@ class Core:
nick_color=color
)
)
popup_on = config.get('information_buffer_popup_on').split()
popup_on = config.getlist('information_buffer_popup_on')
if isinstance(self.tabs.current_tab, tabs.RosterInfoTab):
self.refresh_window()
elif typ != '' and typ.lower() in popup_on:
popup_time = config.get('popup_time') + (nb_lines - 1) * 2
popup_time = config.getint('popup_time') + (nb_lines - 1) * 2
self._pop_information_win_up(nb_lines, popup_time)
else:
if self.information_win_size != 0:
......@@ -1553,7 +1553,7 @@ class Core:
"""
Enable/disable the left panel.
"""
enabled = config.get('enable_vertical_tab_list')
enabled = config.getbool('enable_vertical_tab_list')
if not config.silent_set('enable_vertical_tab_list', str(not enabled)):
self.information('Unable to write in the config file', 'Error')
self.call_for_resize()
......@@ -1576,14 +1576,14 @@ class Core:
Resize the GlobalInfoBar only once at each resize
"""
height, width = self.stdscr.getmaxyx()
if config.get('enable_vertical_tab_list'):
if config.getbool('enable_vertical_tab_list'):
if self.size.core_degrade_x:
return
try:
height, _ = self.stdscr.getmaxyx()
truncated_win = self.stdscr.subwin(
height, config.get('vertical_tab_list_size'), 0, 0)
height, config.getint('vertical_tab_list_size'), 0, 0)
except:
log.error('Curses error on infobar resize', exc_info=True)
return
......@@ -1609,11 +1609,13 @@ class Core:
# the screen that they can occupy, and we draw the tab list on the
# remaining space, on the left
height, width = self.stdscr.getmaxyx()
if (config.get('enable_vertical_tab_list')
if (config.getbool('enable_vertical_tab_list')
and not self.size.core_degrade_x):
try:
scr = self.stdscr.subwin(0,
config.get('vertical_tab_list_size'))
scr = self.stdscr.subwin(
0,
config.getint('vertical_tab_list_size')
)
except:
log.error('Curses error on resize', exc_info=True)
return
......@@ -1623,7 +1625,7 @@ class Core:
self.resize_global_info_bar()
self.resize_global_information_win()
for tab in self.tabs:
if config.get('lazy_resize'):
if config.getbool('lazy_resize'):
tab.need_resize = True
else:
tab.resize()
......@@ -1691,7 +1693,7 @@ class Core:
def join_initial_rooms(self, bookmarks: List[Bookmark]):
"""Join all rooms given in the iterator `bookmarks`"""
for bm in bookmarks:
if not (bm.autojoin or config.get('open_all_bookmarks')):
if not (bm.autojoin or config.getbool('open_all_bookmarks')):
continue
tab = self.tabs.by_name_and_class(bm.jid, tabs.MucTab)
nick = bm.nick if bm.nick else self.own_nick
......@@ -1710,7 +1712,7 @@ class Core:
self.bookmarks.available_storage['private'] = private
self.bookmarks.available_storage['pep'] = pep_
if not self.xmpp.anon and config.get('use_remote_bookmarks'):
if not self.xmpp.anon and config.getbool('use_remote_bookmarks'):
try:
await self.bookmarks.get_remote(self.xmpp, self.information)
except IqError as error:
......@@ -1746,9 +1748,9 @@ class Core:
msg = 'To provide a password in order to join the room, type "/join / password" (replace "password" by the real password)'
tab.add_message(InfoMessage(msg), typ=2)
if code == '409':
if config.get('alternative_nickname') != '':
if config.getstr('alternative_nickname') != '':
if not tab.joined:
tab.own_nick += config.get('alternative_nickname')
tab.own_nick += config.getstr('alternative_nickname')
tab.join()
else:
if not tab.joined:
......
......@@ -94,7 +94,7 @@ class HandlerCore:
rostertab.check_saslexternal(features)
rostertab.check_blocking(features)
self.core.check_blocking(features)
if (config.get('enable_carbons')
if (config.getbool('enable_carbons')
and 'urn:xmpp:carbons:2' in features):
self.core.xmpp.plugin['xep_0280'].enable()
await self.core.check_bookmark_storage(features)
......@@ -230,7 +230,7 @@ class HandlerCore:
if password:
msg += ". The password is \"%s\"." % password
self.core.information(msg, 'Info')
if 'invite' in config.get('beep_on').split():
if 'invite' in config.getlist('beep_on'):
curses.beep()
logger.log_roster_change(inviter.full, 'invited you to %s' % jid.full)
self.core.pending_invites[jid.bare] = inviter.full
......@@ -261,7 +261,7 @@ class HandlerCore:
msg += "\nreason: %s" % reason
self.core.information(msg, 'Info')
if 'invite' in config.get('beep_on').split():
if 'invite' in config.getlist('beep_on'):
curses.beep()
self.core.pending_invites[room.bare] = inviter.full
......@@ -353,7 +353,7 @@ class HandlerCore:
if conv_jid.bare in roster:
remote_nick = roster[conv_jid.bare].name
# check for a received nick
if not remote_nick and config.get('enable_user_nick'):
if not remote_nick and config.getbool('enable_user_nick'):
if message.xml.find(
'{http://jabber.org/protocol/nick}nick') is not None:
remote_nick = message['nick']['nick']
......@@ -425,7 +425,7 @@ class HandlerCore:
typ=1,
)
if not own and 'private' in config.get('beep_on').split():
if not own and 'private' in config.getlist('beep_on'):
if not config.get_by_tabname('disable_beep', conv_jid.bare):
curses.beep()
if self.core.tabs.current_tab is not conversation:
......@@ -646,7 +646,7 @@ class HandlerCore:
current.input.refresh()
self.core.doupdate()
if 'message' in config.get('beep_on').split():
if 'message' in config.getlist('beep_on'):
if (not config.get_by_tabname('disable_beep', room_from)
and self.core.own_nick != message['from'].resource):
curses.beep()
......@@ -731,7 +731,7 @@ class HandlerCore:
else:
tab.last_remote_message = datetime.now()
if not sent and 'private' in config.get('beep_on').split():
if not sent and 'private' in config.getlist('beep_on'):
if not config.get_by_tabname('disable_beep', jid.full):
curses.beep()
if tab is self.core.tabs.current_tab:
......@@ -1095,14 +1095,14 @@ class HandlerCore:
"""
When we are disconnected from remote server
"""
if 'disconnect' in config.get('beep_on').split():
if 'disconnect' in config.getlist('beep_on'):
curses.beep()
# Stop the ping plugin. It would try to send stanza on regular basis
self.core.xmpp.plugin['xep_0199'].disable_keepalive()
msg_typ = 'Error' if not self.core.legitimate_disconnect else 'Info'
self.core.information("Disconnected from server%s." % (event and ": %s" % event or ""), msg_typ)
if self.core.legitimate_disconnect or not config.get(
'auto_reconnect', True):
if self.core.legitimate_disconnect or not config.getbool(
'auto_reconnect'):
return
if (self.core.last_stream_error
and self.core.last_stream_error[1]['condition'] in (
......@@ -1166,7 +1166,7 @@ class HandlerCore:
self.core.xmpp.get_roster()
roster.update_contact_groups(self.core.xmpp.boundjid.bare)
# send initial presence
if config.get('send_initial_presence'):
if config.getbool('send_initial_presence'):
pres = self.core.xmpp.make_presence()
pres['show'] = self.core.status.show
pres['status'] = self.core.status.message
......@@ -1176,7 +1176,7 @@ class HandlerCore:
# join all the available bookmarks. As of yet, this is just the local ones