Unverified Commit d55cc587 authored by mathieui's avatar mathieui

yapf -ir

parent 92496db8
......@@ -8,5 +8,6 @@ def run():
sys.exit(1)
return 0
if __name__ == '__main__':
run()
......@@ -6,23 +6,37 @@ There is a fallback to the deprecated optparse if argparse is not found
from os import path
from argparse import ArgumentParser, SUPPRESS
def parse_args(CONFIG_PATH=''):
"""
Parse the arguments from the command line
"""
parser = ArgumentParser('poezio')
parser.add_argument("-c", "--check-config", dest="check_config",
action='store_true',
help='Check the config file')
parser.add_argument("-d", "--debug", dest="debug",
help="The file where debug will be written",
metavar="DEBUG_FILE")
parser.add_argument("-f", "--file", dest="filename",
default=path.join(CONFIG_PATH, 'poezio.cfg'),
help="The config file you want to use",
metavar="CONFIG_FILE")
parser.add_argument("-v", "--version", dest="version",
help=SUPPRESS, metavar="VERSION",
default="1.0-dev")
parser.add_argument(
"-c",
"--check-config",
dest="check_config",
action='store_true',
help='Check the config file')
parser.add_argument(
"-d",
"--debug",
dest="debug",
help="The file where debug will be written",
metavar="DEBUG_FILE")
parser.add_argument(
"-f",
"--file",
dest="filename",
default=path.join(CONFIG_PATH, 'poezio.cfg'),
help="The config file you want to use",
metavar="CONFIG_FILE")
parser.add_argument(
"-v",
"--version",
dest="version",
help=SUPPRESS,
metavar="VERSION",
default="1.0-dev")
options = parser.parse_args()
return options
......@@ -28,6 +28,7 @@ def monkey_patch_asyncio_slixmpp():
if self._idle:
handle = self._idle.popleft()
handle._run()
cls = asyncio.get_event_loop().__class__
cls._idle = collections.deque()
cls.idle_call = idle_call
......@@ -35,8 +36,8 @@ def monkey_patch_asyncio_slixmpp():
cls._run_once = my_run_once
spawn_event = slixmpp.xmlstream.XMLStream._spawn_event
def patchy(self, xml):
self.loop.idle_call(functools.partial(spawn_event, self, xml))
slixmpp.xmlstream.XMLStream._spawn_event = patchy
slixmpp.xmlstream.XMLStream._spawn_event = patchy
......@@ -40,8 +40,13 @@ log = logging.getLogger(__name__)
class Bookmark(object):
def __init__(self, jid, name=None, autojoin=False, nick=None, password=None, method='local'):
def __init__(self,
jid,
name=None,
autojoin=False,
nick=None,
password=None,
method='local'):
self.jid = jid
self.name = name or jid
self.autojoin = autojoin
......@@ -61,9 +66,8 @@ class Bookmark(object):
self._method = value
def __repr__(self):
return '<%s%s|%s>' % (self.jid,
('/'+self.nick) if self.nick else '',
self.method)
return '<%s%s|%s>' % (self.jid, ('/' + self.nick)
if self.nick else '', self.method)
def stanza(self):
"""
......@@ -98,7 +102,8 @@ class Bookmark(object):
"""
jid = el.get('jid')
name = el.get('name')
autojoin = True if el.get('autojoin', 'false').lower() in ('true', '1') else False
autojoin = True if el.get('autojoin',
'false').lower() in ('true', '1') else False
nick = None
for n in el.iter('nick'):
nick = n.text
......@@ -121,8 +126,8 @@ class Bookmark(object):
name = el['name']
return Bookmark(jid, name, autojoin, nick, password, method='remote')
class BookmarkList(object):
class BookmarkList(object):
def __init__(self):
self.bookmarks = []
preferred = config.get('use_bookmarks_method').lower()
......@@ -191,17 +196,21 @@ class BookmarkList(object):
method = 'xep_0049' if self.preferred == 'privatexml' else 'xep_0223'
if method:
xmpp.plugin['xep_0048'].set_bookmarks(stanza_storage(self.bookmarks),
method=method,
callback=callback)
xmpp.plugin['xep_0048'].set_bookmarks(
stanza_storage(self.bookmarks),
method=method,
callback=callback)
def save_local(self):
"""Save the local bookmarks."""
local = ''.join(bookmark.local() for bookmark in self if bookmark.method == 'local')
local = ''.join(bookmark.local() for bookmark in self
if bookmark.method == 'local')
config.set_and_save('rooms', local)
def save(self, xmpp, core=None, callback=None):
"""Save all the bookmarks."""
self.save_local()
def _cb(iq):
if callback:
callback(iq)
......@@ -209,14 +218,17 @@ class BookmarkList(object):
core.information('Could not save remote bookmarks.', 'Error')
elif core:
core.information('Bookmarks saved', 'Info')
if config.get('use_remote_bookmarks'):
self.save_remote(xmpp, _cb)
def get_pep(self, xmpp, callback):
"""Add the remotely stored bookmarks via pep to the list."""
def _cb(iq):
if iq['type'] == 'result':
for conf in iq['pubsub']['items']['item']['bookmarks']['conferences']:
for conf in iq['pubsub']['items']['item']['bookmarks'][
'conferences']:
if isinstance(conf, URL):
continue
b = Bookmark.parse(conf)
......@@ -230,6 +242,7 @@ class BookmarkList(object):
"""
Fetch the remote bookmarks stored via privatexml.
"""
def _cb(iq):
if iq['type'] == 'result':
for conf in iq['private']['bookmarks']['conferences']:
......@@ -250,12 +263,15 @@ class BookmarkList(object):
if force and not any(self.available_storage.values()):
old_callback = callback
method = 'pep' if self.preferred == 'pep' else 'privatexml'
def new_callback(result):
if result['type'] != 'error':
self.available_storage[method] = True
old_callback(result)
else:
information('No remote bookmark storage available', 'Warning')
information('No remote bookmark storage available',
'Warning')
callback = new_callback
if self.preferred == 'pep':
......@@ -277,10 +293,17 @@ class BookmarkList(object):
nick = jid.resource
else:
nick = None
passwd = config.get_by_tabname('password', jid.bare, fallback=False) or None
b = Bookmark(jid.bare, autojoin=True, nick=nick, password=passwd, method='local')
passwd = config.get_by_tabname(
'password', jid.bare, fallback=False) or None
b = Bookmark(
jid.bare,
autojoin=True,
nick=nick,
password=passwd,
method='local')
self.append(b)
def stanza_storage(bookmarks):
"""Generate a <storage/> stanza with the conference elements."""
storage = Bookmarks()
......
......@@ -4,7 +4,6 @@
#
# Poezio is free software: you can redistribute it and/or modify
# it under the terms of the zlib license. See the COPYING file.
"""
Various useful functions.
"""
......@@ -45,6 +44,7 @@ def get_base64_from_file(path):
mime_type = mimetypes.guess_type(path)[0]
return (encoded, mime_type, sha1)
def _get_output_of_command(command):
"""
Runs a command and returns its output.
......@@ -54,10 +54,12 @@ def _get_output_of_command(command):
:rtype: :py:class:`str`
"""
try:
return subprocess.check_output(command.split()).decode('utf-8').split('\n')
return subprocess.check_output(
command.split()).decode('utf-8').split('\n')
except subprocess.CalledProcessError:
return None
def _is_in_path(command, return_abs_path=False):
"""
Check if *command* is in the $PATH or not.
......@@ -81,6 +83,7 @@ def _is_in_path(command, return_abs_path=False):
pass
return False
DISTRO_INFO = {
'Arch Linux': '/etc/arch-release',
'Aurox Linux': '/etc/aurox-release',
......@@ -103,6 +106,7 @@ DISTRO_INFO = {
'Redhat Linux': '/etc/redhat-release'
}
def get_os_info():
"""
Returns a detailed and well formated string containing
......@@ -116,10 +120,12 @@ def get_os_info():
full_path_to_executable = _is_in_path(executable, return_abs_path=True)
if full_path_to_executable:
command = executable + params
process = subprocess.Popen([command], shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
close_fds=True)
process = subprocess.Popen(
[command],
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
close_fds=True)
process.wait()
output = process.stdout.readline().decode('utf-8').strip()
# some distros put n/a in places, so remove those
......@@ -136,7 +142,7 @@ def get_os_info():
text = _get_output_of_command(path_to_file)[0]
else:
fdes = open(path_to_file, encoding='utf-8')
text = fdes.readline().strip() # get only first line
text = fdes.readline().strip() # get only first line
fdes.close()
if path_to_file.endswith('version'):
# sourcemage_version and slackware-version files
......@@ -158,11 +164,12 @@ def get_os_info():
# our last chance, ask uname and strip it
uname_output = _get_output_of_command('uname -sr')
if uname_output is not None:
os_info = uname_output[0] # only first line
os_info = uname_output[0] # only first line
return os_info
os_info = 'N/A'
return os_info
def _datetime_tuple(timestamp):
"""
Convert a timestamp using strptime and the format: %Y%m%dT%H:%M:%S.
......@@ -194,7 +201,7 @@ def _datetime_tuple(timestamp):
tz_msg = timedelta(seconds=tz_mod * tz_msg)
ret -= tz_msg
except ValueError:
pass # ignore if we got a badly-formatted offset
pass # ignore if we got a badly-formatted offset
# convert UTC to local time, with DST etc.
if time.daylight and time.localtime().tm_isdst:
tz = timedelta(seconds=-time.altzone)
......@@ -203,6 +210,7 @@ def _datetime_tuple(timestamp):
ret += tz
return ret
def get_utc_time(local_time=None):
"""
Get the current UTC time
......@@ -225,6 +233,7 @@ def get_utc_time(local_time=None):
return utc_time
def get_local_time(utc_time):
"""
Get the local time from an UTC time
......@@ -240,6 +249,7 @@ def get_local_time(utc_time):
return local_time
def find_delayed_tag(message):
"""
Check if a message is delayed or not.
......@@ -266,6 +276,7 @@ def find_delayed_tag(message):
date = None
return (delayed, date)
def shell_split(st):
"""
Split a string correctly according to the quotes
......@@ -288,6 +299,7 @@ def shell_split(st):
w = sh.get_token()
return ret
def find_argument(pos, text, quoted=True):
"""
Split an input into a list of arguments, return the number of the
......@@ -308,6 +320,7 @@ def find_argument(pos, text, quoted=True):
else:
return _find_argument_unquoted(pos, text)
def _find_argument_quoted(pos, text):
"""
Get the number of the argument at position pos in
......@@ -324,6 +337,7 @@ def _find_argument_quoted(pos, text):
return count + 1
def _find_argument_unquoted(pos, text):
"""
Get the number of the argument at position pos in
......@@ -341,6 +355,7 @@ def _find_argument_unquoted(pos, text):
argnum = i
return argnum + 1
def parse_str_to_secs(duration=''):
"""
Parse a string of with a number of d, h, m, s.
......@@ -368,6 +383,7 @@ def parse_str_to_secs(duration=''):
result += int(tmp)
return result
def parse_secs_to_str(duration=0):
"""
Do the reverse operation of :py:func:`parse_str_to_secs`.
......@@ -397,6 +413,7 @@ def parse_secs_to_str(duration=0):
result = '0s'
return result
def format_tune_string(infos):
"""
Contruct a string from a dict created from an "User tune" event.
......@@ -434,6 +451,7 @@ def format_tune_string(infos):
elems.append('[' + mins + ':' + secs + ']')
return ' '.join(elems)
def format_gaming_string(infos):
"""
Construct a string from a dict containing "user gaming" information.
......@@ -452,6 +470,7 @@ def format_gaming_string(infos):
return '%s on %s' % (name, server_address)
return name
def safeJID(*args, **kwargs):
"""
Construct a :py:class:`slixmpp.JID` object from a string.
......@@ -463,4 +482,3 @@ def safeJID(*args, **kwargs):
return JID(*args, **kwargs)
except InvalidJID:
return JID('')
......@@ -144,14 +144,15 @@ DEFAULT_CONFIG = {
'folded_roster_groups': '',
'info_win_height': 2
},
'muc_colors': {
}
'muc_colors': {}
}
class Config(RawConfigParser):
"""
load/save the config to a file
"""
def __init__(self, file_name, default=None):
RawConfigParser.__init__(self, None)
# make the options case sensitive
......@@ -198,8 +199,12 @@ class Config(RawConfigParser):
return default
return res
def get_by_tabname(self, option, tabname,
fallback=True, fallback_server=True, default=''):
def get_by_tabname(self,
option,
tabname,
fallback=True,
fallback_server=True,
default=''):
"""
Try to get the value for the option. First we look in
a section named `tabname`, if the option is not present
......@@ -232,7 +237,6 @@ class Config(RawConfigParser):
return self.get(option, default)
return default
def __get(self, option, section=DEFSECTION, **kwargs):
"""
facility for RawConfigParser.get
......@@ -331,11 +335,7 @@ class Config(RawConfigParser):
prefix, file = path.split(self.file_name)
filename = path.join(prefix, '.%s.tmp' % file)
fd = os.fdopen(
os.open(
filename,
os.O_WRONLY | os.O_CREAT,
0o600),
'w')
os.open(filename, os.O_WRONLY | os.O_CREAT, 0o600), 'w')
for line in lines:
fd.write('%s\n' % line)
fd.close()
......@@ -362,9 +362,10 @@ class Config(RawConfigParser):
with open(self.file_name, 'r', encoding='utf-8') as df:
lines_before = [line.strip() for line in df]
except OSError:
log.error('Unable to read the config file %s',
self.file_name,
exc_info=True)
log.error(
'Unable to read the config file %s',
self.file_name,
exc_info=True)
return tuple()
else:
lines_before = []
......@@ -415,8 +416,7 @@ class Config(RawConfigParser):
else:
return ('Could not toggle option: %s.'
' Current value is %s.' %
(option, current or "empty"),
'Warning')
(option, current or "empty"), 'Warning')
if self.has_section(section):
RawConfigParser.set(self, section, option, value)
else:
......@@ -477,12 +477,13 @@ def find_line(lines, start, end, option):
"""
current = start
for line in lines[start:end]:
if (line.startswith('%s ' % option) or
line.startswith('%s=' % option)):
if (line.startswith('%s ' % option)
or line.startswith('%s=' % option)):
return current
current += 1
return -1
def file_ok(filepath):
"""
Returns True if the file exists and is readable and writeable,
......@@ -492,6 +493,7 @@ def file_ok(filepath):
val &= os.access(filepath, os.R_OK | os.W_OK)
return bool(val)
def check_create_config_dir():
"""
create the configuration directory if it doesn't exist
......@@ -507,6 +509,7 @@ def check_create_config_dir():
pass
return CONFIG_PATH
def check_create_cache_dir():
"""
create the cache directory if it doesn't exist
......@@ -525,6 +528,7 @@ def check_create_cache_dir():
except OSError:
pass
def check_config():
"""
Check the config file and print results
......@@ -533,7 +537,8 @@ def check_config():
for option in DEFAULT_CONFIG['Poezio']:
value = config.get(option)
if value != DEFAULT_CONFIG['Poezio'][option]:
result['changed'].append((option, value, DEFAULT_CONFIG['Poezio'][option]))
result['changed'].append((option, value,
DEFAULT_CONFIG['Poezio'][option]))
else:
value = config.get(option, default='')
upper = value.upper()
......@@ -544,15 +549,19 @@ def check_config():
result['changed'].sort(key=lambda x: x[0])
result['missing'].sort()
if result['changed']:
print('\033[1mOptions changed from the default configuration:\033[0m\n')
print(
'\033[1mOptions changed from the default configuration:\033[0m\n')
for option, new_value, default in result['changed']:
print(' \033[1m%s\033[0m = \033[33m%s\033[0m (default: \033[32m%s\033[0m)' % (option, new_value, default))
print(
' \033[1m%s\033[0m = \033[33m%s\033[0m (default: \033[32m%s\033[0m)'
% (option, new_value, default))
if result['missing']:
print('\n\033[1mMissing options:\033[0m (the defaults are used)\n')
for option in result['missing']:
print(' \033[31m%s\033[0m' % option)
def run_cmdline_args(CONFIG_PATH):
"Parse the command line arguments"
global options
......@@ -560,7 +569,8 @@ def run_cmdline_args(CONFIG_PATH):
# Copy a default file if none exists
if not path.isfile(options.filename):
default = path.join(path.dirname(__file__), '../data/default_config.cfg')
default = path.join(
path.dirname(__file__), '../data/default_config.cfg')
other = pkg_resources.resource_filename('poezio', 'default_config.cfg')
if path.isfile(default):
copy2(default, options.filename)
......@@ -577,6 +587,7 @@ def run_cmdline_args(CONFIG_PATH):
global firstrun
firstrun = True
def create_global_config():
"Create the global config object, or crash"
try:
......@@ -589,6 +600,7 @@ def create_global_config():
traceback.print_exc(limit=0)
sys.exit(1)
def check_create_log_dir():
"Create the poezio logging directory if it doesn’t exist"
global LOG_DIR
......@@ -610,29 +622,29 @@ def check_create_log_dir():
except:
pass
def setup_logging():
"Change the logging config according to the cmdline options and config"
if config.get('log_errors'):
LOGGING_CONFIG['root']['handlers'].append('error')
LOGGING_CONFIG['handlers']['error'] = {
'level': 'ERROR',
'class': 'logging.FileHandler',
'filename': path.join(LOG_DIR, 'errors.log'),
'formatter': 'simple',
}
'level': 'ERROR',
'class': 'logging.FileHandler',
'filename': path.join(LOG_DIR, 'errors.log'),
'formatter': 'simple',
}
logging.disable(logging.WARNING)
if options.debug:
LOGGING_CONFIG['root']['handlers'].append('debug')
LOGGING_CONFIG['handlers']['debug'] = {
'level':'DEBUG',
'class':'logging.FileHandler',
'filename': options.debug,
'formatter': 'simple',
}
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': options.debug,
'formatter': 'simple',
}
logging.disable(logging.NOTSET)
if LOGGING_CONFIG['root']['handlers']:
logging.config.dictConfig(LOGGING_CONFIG)
else:
......@@ -642,6 +654,7 @@ def setup_logging():
global log
log = logging.getLogger(__name__)
def post_logging_setup():
# common imports slixmpp, which creates then its loggers, so
# it needs to be after logger configuration
......@@ -649,6 +662,7 @@ def post_logging_setup():
global safeJID
safeJID = JID
LOGGING_CONFIG = {
'version': 1,
'disable_existing_loggers': True,
......@@ -657,12 +671,11 @@ LOGGING_CONFIG = {
'format': '%(asctime)s %(levelname)s:%(module)s:%(message)s'
}
},
'handlers': {
},
'handlers': {},
'root': {
'handlers': [],
'propagate': True,
'level': 'DEBUG',
'handlers': [],
'propagate': True,
'level': 'DEBUG',
}
}
......