code style reformatting using black

This commit is contained in:
Goffi 2018-06-27 20:14:46 +02:00
commit 744cb0c503

View file

@ -23,6 +23,7 @@ from sat.core import exceptions
from twisted.words.protocols.jabber import jid
from twisted.internet import defer
from sat.core.log import getLogger
log = getLogger(__name__)
from twisted.python import failure
from collections import OrderedDict
@ -35,26 +36,29 @@ PLUGIN_INFO = {
C.PI_DEPENDENCIES: [],
C.PI_MAIN: "TextCommands",
C.PI_HANDLER: "no",
C.PI_DESCRIPTION: _("""IRC like text commands""")
C.PI_DESCRIPTION: _("""IRC like text commands"""),
}
class InvalidCommandSyntax(Exception):
"""Throwed while parsing @command in docstring if syntax is invalid"""
pass
CMD_KEY = "@command"
CMD_TYPES = ('group', 'one2one', 'all')
CMD_TYPES = ("group", "one2one", "all")
FEEDBACK_INFO_TYPE = "TEXT_CMD"
class TextCommands(object):
#FIXME: doc strings for commands have to be translatable
# FIXME: doc strings for commands have to be translatable
# plugins need a dynamic translation system (translation
# should be downloadable independently)
HELP_SUGGESTION = _("Type '/help' to get a list of the available commands. If you didn't want to use a command, please start your message with '//' to escape the slash.")
HELP_SUGGESTION = _(
"Type '/help' to get a list of the available commands. If you didn't want to use a command, please start your message with '//' to escape the slash."
)
def __init__(self, host):
log.info(_("Text commands initialization"))
@ -78,9 +82,7 @@ class TextCommands(object):
- "args" (default: ""): the arguments available, using syntax specified in documentation.
- "doc_arg_[name]": the doc of [name] argument
"""
data = OrderedDict([('doc_short_help', ""),
('type', 'all'),
('args', '')])
data = OrderedDict([("doc_short_help", ""), ("type", "all"), ("args", "")])
docstring = cmd.__doc__
if docstring is None:
log.warning(u"Not docstring found for command {}".format(cmd_name))
@ -90,18 +92,22 @@ class TextCommands(object):
data["doc_short_help"] = doc_data[0]
try:
cmd_indent = 0 # >0 when @command is found are we are parsing it
cmd_indent = 0 # >0 when @command is found are we are parsing it
for line in doc_data:
stripped = line.strip()
if cmd_indent and line[cmd_indent:cmd_indent+5] == " -":
if cmd_indent and line[cmd_indent : cmd_indent + 5] == " -":
colon_idx = line.find(":")
if colon_idx == -1:
raise InvalidCommandSyntax("No colon found in argument description")
arg_name = line[cmd_indent+6:colon_idx].strip()
raise InvalidCommandSyntax(
"No colon found in argument description"
)
arg_name = line[cmd_indent + 6 : colon_idx].strip()
if not arg_name:
raise InvalidCommandSyntax("No name found in argument description")
arg_help = line[colon_idx+1:].strip()
raise InvalidCommandSyntax(
"No name found in argument description"
)
arg_help = line[colon_idx + 1 :].strip()
data["doc_arg_{}".format(arg_name)] = arg_help
elif cmd_indent:
# we are parsing command and indent level is not good, it's finished
@ -113,31 +119,36 @@ class TextCommands(object):
colon_idx = stripped.find(":")
if colon_idx == -1:
raise InvalidCommandSyntax("missing colon")
type_data = stripped[len(CMD_KEY):colon_idx].strip()
type_data = stripped[len(CMD_KEY) : colon_idx].strip()
if len(type_data) == 0:
type_data="(all)"
elif len(type_data) <= 2 or type_data[0] != '(' or type_data[-1] != ')':
type_data = "(all)"
elif (
len(type_data) <= 2 or type_data[0] != "(" or type_data[-1] != ")"
):
raise InvalidCommandSyntax("Bad type data syntax")
type_ = type_data[1:-1]
if type_ not in CMD_TYPES:
raise InvalidCommandSyntax("Unknown type {}".format(type_))
data["type"] = type_
#args
data["args"] = stripped[colon_idx+1:].strip()
# args
data["args"] = stripped[colon_idx + 1 :].strip()
except InvalidCommandSyntax as e:
log.warning(u"Invalid command syntax for command {command}: {message}".format(command=cmd_name, message=e.message))
log.warning(
u"Invalid command syntax for command {command}: {message}".format(
command=cmd_name, message=e.message
)
)
return data
def registerTextCommands(self, instance):
""" Add a text command
@param instance: instance of a class containing text commands
"""
for attr in dir(instance):
if attr.startswith('cmd_'):
if attr.startswith("cmd_"):
cmd = getattr(instance, attr)
if not callable(cmd):
log.warning(_(u"Skipping not callable [%s] attribute") % attr)
@ -146,13 +157,19 @@ class TextCommands(object):
if not cmd_name:
log.warning(_("Skipping cmd_ method"))
if cmd_name in self._commands:
suff=2
suff = 2
while (cmd_name + str(suff)) in self._commands:
suff+=1
suff += 1
new_name = cmd_name + str(suff)
log.warning(_(u"Conflict for command [{old_name}], renaming it to [{new_name}]").format(old_name=cmd_name, new_name=new_name))
log.warning(
_(
u"Conflict for command [{old_name}], renaming it to [{new_name}]"
).format(old_name=cmd_name, new_name=new_name)
)
cmd_name = new_name
self._commands[cmd_name] = cmd_data = OrderedDict({'callback':cmd}) # We use an Ordered dict to keep documenation order
self._commands[cmd_name] = cmd_data = OrderedDict(
{"callback": cmd}
) # We use an Ordered dict to keep documenation order
cmd_data.update(self._parseDocString(cmd, cmd_name))
log.info(_("Registered text command [%s]") % cmd_name)
@ -168,7 +185,9 @@ class TextCommands(object):
self._whois.append((priority, callback))
self._whois.sort(key=lambda item: item[0], reverse=True)
def sendMessageTrigger(self, client, mess_data, pre_xml_treatments, post_xml_treatments):
def sendMessageTrigger(
self, client, mess_data, pre_xml_treatments, post_xml_treatments
):
"""Install SendMessage command hook """
pre_xml_treatments.addCallback(self._sendMessageCmdHook, client)
return True
@ -185,8 +204,8 @@ class TextCommands(object):
@param profile: %(doc_profile)s
"""
try:
msg = mess_data["message"]['']
msg_lang = ''
msg = mess_data["message"][""]
msg_lang = ""
except KeyError:
try:
# we have not default message, we try to take the first found
@ -196,18 +215,18 @@ class TextCommands(object):
return mess_data
try:
if msg[:2] == '//':
if msg[:2] == "//":
# we have a double '/', it's the escape sequence
mess_data["message"][msg_lang] = msg[1:]
return mess_data
if msg[0] != '/':
if msg[0] != "/":
return mess_data
except IndexError:
return mess_data
# we have a command
d = None
command = msg[1:].partition(' ')[0].lower()
command = msg[1:].partition(" ")[0].lower()
if command.isalpha():
# looks like an actual command, we try to call the corresponding method
def retHandling(ret):
@ -229,19 +248,33 @@ class TextCommands(object):
self.feedBack(client, u"Command failed {}".format(msg), mess_data)
return False
mess_data["unparsed"] = msg[1 + len(command):] # part not yet parsed of the message
mess_data["unparsed"] = msg[
1 + len(command) :
] # part not yet parsed of the message
try:
cmd_data = self._commands[command]
except KeyError:
self.feedBack(client, _("Unknown command /%s. ") % command + self.HELP_SUGGESTION, mess_data)
self.feedBack(
client,
_("Unknown command /%s. ") % command + self.HELP_SUGGESTION,
mess_data,
)
log.debug("text command help message")
raise failure.Failure(exceptions.CancelError())
else:
if not self._contextValid(mess_data, cmd_data):
# The command is not launched in the right context, we throw a message with help instructions
context_txt = _("group discussions") if cmd_data["type"] == "group" else _("one to one discussions")
feedback = _("/{command} command only applies in {context}.").format(command=command, context=context_txt)
self.feedBack(client, u"{} {}".format(feedback, self.HELP_SUGGESTION), mess_data)
context_txt = (
_("group discussions")
if cmd_data["type"] == "group"
else _("one to one discussions")
)
feedback = _("/{command} command only applies in {context}.").format(
command=command, context=context_txt
)
self.feedBack(
client, u"{} {}".format(feedback, self.HELP_SUGGESTION), mess_data
)
log.debug("text command invalid message")
raise failure.Failure(exceptions.CancelError())
else:
@ -249,7 +282,9 @@ class TextCommands(object):
d.addErrback(genericErrback)
d.addCallback(retHandling)
return d or mess_data # if a command is detected, we should have a deferred, else we send the message normally
return (
d or mess_data
) # if a command is detected, we should have a deferred, else we send the message normally
def _contextValid(self, mess_data, cmd_data):
"""Tell if a command can be used in the given context
@ -258,8 +293,9 @@ class TextCommands(object):
@param cmd_data(dict): command data as returned by self._parseDocString
@return (bool): True if command can be used in this context
"""
if ((cmd_data['type'] == "group" and mess_data["type"] != "groupchat") or
(cmd_data['type'] == 'one2one' and mess_data["type"] == "groupchat")):
if (cmd_data["type"] == "group" and mess_data["type"] != "groupchat") or (
cmd_data["type"] == "one2one" and mess_data["type"] == "groupchat"
):
return False
return True
@ -270,16 +306,16 @@ class TextCommands(object):
or a shortcut (e.g.: sat or sat@ for sat on current service)
@param service_jid: jid of the current service (e.g.: chat.jabberfr.org)
"""
nb_arobas = arg.count('@')
nb_arobas = arg.count("@")
if nb_arobas == 1:
if arg[-1] != '@':
if arg[-1] != "@":
return jid.JID(arg)
return jid.JID(arg + service_jid)
return jid.JID(u"%s@%s" % (arg, service_jid))
def feedBack(self, client, message, mess_data, info_type=FEEDBACK_INFO_TYPE):
"""Give a message back to the user"""
if mess_data["type"] == 'groupchat':
if mess_data["type"] == "groupchat":
to_ = mess_data["to"].userhostJID()
else:
to_ = client.jid
@ -288,7 +324,7 @@ class TextCommands(object):
mess_data["from"] = mess_data["to"]
mess_data["to"] = to_
mess_data["type"] = C.MESS_TYPE_INFO
mess_data["message"] = {'': message}
mess_data["message"] = {"": message}
mess_data["extra"]["info_type"] = info_type
client.messageSendToBridge(mess_data)
@ -303,7 +339,7 @@ class TextCommands(object):
entity = mess_data["unparsed"].strip()
if mess_data['type'] == "groupchat":
if mess_data["type"] == "groupchat":
room = mess_data["to"].userhostJID()
try:
if self.host.plugins["XEP-0045"].isNickInRoom(client, room, entity):
@ -325,11 +361,13 @@ class TextCommands(object):
if not target_jid.resource:
target_jid.resource = self.host.memory.getMainResource(client, target_jid)
whois_msg = [_(u"whois for %(jid)s") % {'jid': target_jid}]
whois_msg = [_(u"whois for %(jid)s") % {"jid": target_jid}]
d = defer.succeed(None)
for ignore, callback in self._whois:
d.addCallback(lambda ignore: callback(client, whois_msg, mess_data, target_jid))
d.addCallback(
lambda ignore: callback(client, whois_msg, mess_data, target_jid)
)
def feedBack(ignore):
self.feedBack(client, u"\n".join(whois_msg), mess_data)
@ -348,7 +386,9 @@ class TextCommands(object):
for doc_name, doc_help in cmd_data.iteritems():
if doc_name.startswith("doc_arg_"):
arg_name = doc_name[8:]
strings.append(u"- {name}: {doc_help}".format(name=arg_name, doc_help=_(doc_help)))
strings.append(
u"- {name}: {doc_help}".format(name=arg_name, doc_help=_(doc_help))
)
return strings
@ -376,7 +416,9 @@ class TextCommands(object):
if cmd_name and cmd_name[0] == "/":
cmd_name = cmd_name[1:]
if cmd_name and cmd_name not in self._commands:
self.feedBack(client, _(u"Invalid command name [{}]\n".format(cmd_name)), mess_data)
self.feedBack(
client, _(u"Invalid command name [{}]\n".format(cmd_name)), mess_data
)
cmd_name = ""
if not cmd_name:
# we show the global help
@ -387,22 +429,27 @@ class TextCommands(object):
cmd_data = self._commands[command]
if not self._contextValid(mess_data, cmd_data):
continue
spaces = (longuest - len(command)) * ' '
help_cmds.append(" /{command}: {spaces} {short_help}".format(
command=command,
spaces=spaces,
short_help=cmd_data["doc_short_help"]
))
spaces = (longuest - len(command)) * " "
help_cmds.append(
" /{command}: {spaces} {short_help}".format(
command=command,
spaces=spaces,
short_help=cmd_data["doc_short_help"],
)
)
help_mess = _(u"Text commands available:\n%s") % (u'\n'.join(help_cmds), )
help_mess = _(u"Text commands available:\n%s") % (u"\n".join(help_cmds),)
else:
# we show detailled help for a command
cmd_data = self._commands[cmd_name]
syntax = cmd_data["args"]
help_mess = _(u"/{name}: {short_help}\n{syntax}{args_help}").format(
name=cmd_name,
short_help=cmd_data['doc_short_help'],
syntax=_(" "*4+"syntax: {}\n").format(syntax) if syntax else "",
args_help=u'\n'.join([u" "*8+"{}".format(line) for line in self._getArgsHelp(cmd_data)]))
short_help=cmd_data["doc_short_help"],
syntax=_(" " * 4 + "syntax: {}\n").format(syntax) if syntax else "",
args_help=u"\n".join(
[u" " * 8 + "{}".format(line) for line in self._getArgsHelp(cmd_data)]
),
)
self.feedBack(client, help_mess, mess_data)