Reformatted code base using black.

This commit is contained in:
Goffi 2024-06-19 18:44:57 +02:00
commit 53fdaa9d09
262 changed files with 12604 additions and 8966 deletions

View file

@ -77,7 +77,8 @@ class Constructor(object):
def get_default(self, name):
"""Return default values of a function in a dict
@param name: Name of the function to get
@return: dict, each key is the integer param number (no key if no default value)"""
@return: dict, each key is the integer param number (no key if no default value)
"""
default_dict = {}
def_re = re.compile(r"param_(\d+)_default")
@ -109,7 +110,8 @@ class Constructor(object):
def get_arguments_doc(self, name):
"""Return documentation of arguments
@param name: Name of the function to get
@return: dict, each key is the integer param number (no key if no argument doc), value is a tuple (name, doc)"""
@return: dict, each key is the integer param number (no key if no argument doc), value is a tuple (name, doc)
"""
doc_dict = {}
option_re = re.compile(r"doc_param_(\d+)")
value_re = re.compile(r"^(\w+): (.*)$", re.MULTILINE | re.DOTALL)
@ -145,8 +147,19 @@ class Constructor(object):
i = 0
while i < len(signature):
if signature[i] not in ["b", "y", "n", "i", "x", "q", "u", "t", "d", "s",
"a"]:
if signature[i] not in [
"b",
"y",
"n",
"i",
"x",
"q",
"u",
"t",
"d",
"s",
"a",
]:
raise ParseError("Unmanaged attribute type [%c]" % signature[i])
if signature[i] == "a":
@ -293,8 +306,9 @@ class Constructor(object):
extend_method(completion, function, default, arg_doc, async_)
for part, fmt in FORMATS.items():
if (part.startswith(function["type"])
or part.startswith(f"async_{function['type']}")):
if part.startswith(function["type"]) or part.startswith(
f"async_{function['type']}"
):
parts[part.upper()].append(fmt.format(**completion))
# at this point, signals_part, methods_part and direct_calls should be filled,
@ -350,10 +364,12 @@ class Constructor(object):
os.mkdir(self.args.dest_dir)
full_path = os.path.join(self.args.dest_dir, filename)
if os.path.exists(full_path) and not self.args.force:
print((
"The destination file [%s] already exists ! Use --force to overwrite it"
% full_path
))
print(
(
"The destination file [%s] already exists ! Use --force to overwrite it"
% full_path
)
)
try:
with open(full_path, "w") as dest_file:
dest_file.write("\n".join(file_buf))

View file

@ -27,14 +27,11 @@ class DbusConstructor(base_constructor.Constructor):
CORE_FORMATS = {
"methods_declarations": """\
Method('{name}', arguments='{sig_in}', returns='{sig_out}'),""",
"methods": """\
def dbus_{name}(self, {args}):
{debug}return self._callback("{name}", {args_no_default})\n""",
"signals_declarations": """\
Signal('{name}', '{sig_in}'),""",
"signals": """\
def {name}(self, {args}):
self._obj.emitSignal("{name}", {args})\n""",
@ -68,7 +65,8 @@ class DbusConstructor(base_constructor.Constructor):
completion.update(
{
"debug": (
"" if not self.args.debug
""
if not self.args.debug
else f'log.debug ("{completion["name"]}")\n{8 * " "}'
)
}
@ -78,9 +76,11 @@ class DbusConstructor(base_constructor.Constructor):
completion.update(
{
# XXX: we can manage blocking call in the same way as async one: if callback is None the call will be blocking
"debug": ""
if not self.args.debug
else 'log.debug ("%s")\n%s' % (completion["name"], 8 * " "),
"debug": (
""
if not self.args.debug
else 'log.debug ("%s")\n%s' % (completion["name"], 8 * " ")
),
"args_result": self.get_arguments(function["sig_in"], name=arg_doc),
"async_args": "callback=None, errback=None",
"async_comma": ", " if function["sig_in"] else "",
@ -95,9 +95,9 @@ class DbusConstructor(base_constructor.Constructor):
)
if async_:
completion["blocking_call"] = ""
completion[
"async_args_result"
] = "timeout=const_TIMEOUT, reply_handler=callback, error_handler=error_handler"
completion["async_args_result"] = (
"timeout=const_TIMEOUT, reply_handler=callback, error_handler=error_handler"
)
else:
# XXX: To have a blocking call, we must have not reply_handler, so we test if callback exists, and add reply_handler only in this case
completion[

View file

@ -31,10 +31,8 @@ log = getLogger(__name__)
# Interface prefix
const_INT_PREFIX = config.config_get(
config.parse_main_conf(),
"",
"bridge_dbus_int_prefix",
"org.libervia.Libervia")
config.parse_main_conf(), "", "bridge_dbus_int_prefix", "org.libervia.Libervia"
)
const_ERROR_PREFIX = const_INT_PREFIX + ".error"
const_OBJ_PATH = "/org/libervia/Libervia/bridge"
const_CORE_SUFFIX = ".core"
@ -88,12 +86,10 @@ class DBusObject(objects.DBusObject):
core_iface = DBusInterface(
const_INT_PREFIX + const_CORE_SUFFIX,
##METHODS_DECLARATIONS_PART##
##SIGNALS_DECLARATIONS_PART##
)
plugin_iface = DBusInterface(
const_INT_PREFIX + const_PLUGIN_SUFFIX
##METHODS_DECLARATIONS_PART##
##SIGNALS_DECLARATIONS_PART##
)
plugin_iface = DBusInterface(const_INT_PREFIX + const_PLUGIN_SUFFIX)
dbusInterfaces = [core_iface, plugin_iface]
@ -116,8 +112,10 @@ class DBusObject(objects.DBusObject):
d.addErrback(GenericException.create_and_raise)
return d
##METHODS_PART##
class bridge:
def __init__(self):
@ -140,7 +138,7 @@ class bridge:
conn.exportObject(self._obj)
await conn.requestBusName(const_INT_PREFIX)
##SIGNALS_PART##
##SIGNALS_PART##
def register_method(self, name, callback):
log.debug(f"registering DBus bridge method [{name}]")
self._obj.register_method(name, callback)
@ -149,7 +147,7 @@ class bridge:
self._obj.emitSignal(name, *args)
def add_method(
self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}
self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}
):
"""Dynamically add a method to D-Bus bridge"""
# FIXME: doc parameter is kept only temporary, the time to remove it from calls
@ -157,10 +155,12 @@ class bridge:
self._obj.plugin_iface.addMethod(
Method(name, arguments=in_sign, returns=out_sign)
)
# we have to create a method here instead of using partialmethod, because txdbus
# uses __func__ which doesn't work with partialmethod
def caller(self_, *args, **kwargs):
return self_._callback(name, *args, **kwargs)
setattr(self._obj, f"dbus_{name}", MethodType(caller, self._obj))
self.register_method(name, method)

View file

@ -33,12 +33,10 @@ log = getLogger(__name__)
# Interface prefix
const_INT_PREFIX = config.config_get(
config.parse_main_conf(),
"",
"bridge_dbus_int_prefix",
"org.libervia.Libervia")
config.parse_main_conf(), "", "bridge_dbus_int_prefix", "org.libervia.Libervia"
)
const_ERROR_PREFIX = const_INT_PREFIX + ".error"
const_OBJ_PATH = '/org/libervia/Libervia/bridge'
const_OBJ_PATH = "/org/libervia/Libervia/bridge"
const_CORE_SUFFIX = ".core"
const_PLUGIN_SUFFIX = ".plugin"
const_TIMEOUT = 120
@ -52,7 +50,7 @@ def dbus_to_bridge_exception(dbus_e):
"""
full_name = dbus_e.get_dbus_name()
if full_name.startswith(const_ERROR_PREFIX):
name = dbus_e.get_dbus_name()[len(const_ERROR_PREFIX) + 1:]
name = dbus_e.get_dbus_name()[len(const_ERROR_PREFIX) + 1 :]
else:
name = full_name
# XXX: dbus_e.args doesn't contain the original DBusException args, but we
@ -62,7 +60,7 @@ def dbus_to_bridge_exception(dbus_e):
try:
message, condition = ast.literal_eval(message)
except (SyntaxError, ValueError, TypeError):
condition = ''
condition = ""
return BridgeException(name, message, condition)
@ -71,24 +69,33 @@ class bridge:
def bridge_connect(self, callback, errback):
try:
self.sessions_bus = dbus.SessionBus()
self.db_object = self.sessions_bus.get_object(const_INT_PREFIX,
const_OBJ_PATH)
self.db_core_iface = dbus.Interface(self.db_object,
dbus_interface=const_INT_PREFIX + const_CORE_SUFFIX)
self.db_plugin_iface = dbus.Interface(self.db_object,
dbus_interface=const_INT_PREFIX + const_PLUGIN_SUFFIX)
self.db_object = self.sessions_bus.get_object(
const_INT_PREFIX, const_OBJ_PATH
)
self.db_core_iface = dbus.Interface(
self.db_object, dbus_interface=const_INT_PREFIX + const_CORE_SUFFIX
)
self.db_plugin_iface = dbus.Interface(
self.db_object, dbus_interface=const_INT_PREFIX + const_PLUGIN_SUFFIX
)
except dbus.exceptions.DBusException as e:
if e._dbus_error_name in ('org.freedesktop.DBus.Error.ServiceUnknown',
'org.freedesktop.DBus.Error.Spawn.ExecFailed'):
if e._dbus_error_name in (
"org.freedesktop.DBus.Error.ServiceUnknown",
"org.freedesktop.DBus.Error.Spawn.ExecFailed",
):
errback(BridgeExceptionNoService())
elif e._dbus_error_name == 'org.freedesktop.DBus.Error.NotSupported':
log.error(_("D-Bus is not launched, please see README to see instructions on how to launch it"))
elif e._dbus_error_name == "org.freedesktop.DBus.Error.NotSupported":
log.error(
_(
"D-Bus is not launched, please see README to see instructions on how to launch it"
)
)
errback(BridgeInitError)
else:
errback(e)
else:
callback()
#props = self.db_core_iface.getProperties()
# props = self.db_core_iface.getProperties()
def register_signal(self, functionName, handler, iface="core"):
if iface == "core":
@ -96,10 +103,10 @@ class bridge:
elif iface == "plugin":
self.db_plugin_iface.connect_to_signal(functionName, handler)
else:
log.error(_('Unknown interface'))
log.error(_("Unknown interface"))
def __getattribute__(self, name):
""" usual __getattribute__ if the method exists, else try to find a plugin method """
"""usual __getattribute__ if the method exists, else try to find a plugin method"""
try:
return object.__getattribute__(self, name)
except AttributeError:
@ -114,20 +121,26 @@ class bridge:
args = list(args)
if kwargs:
if 'callback' in kwargs:
if "callback" in kwargs:
async_ = True
_callback = kwargs.pop('callback')
_errback = kwargs.pop('errback', lambda failure: log.error(str(failure)))
_callback = kwargs.pop("callback")
_errback = kwargs.pop(
"errback", lambda failure: log.error(str(failure))
)
try:
args.append(kwargs.pop('profile'))
args.append(kwargs.pop("profile"))
except KeyError:
try:
args.append(kwargs.pop('profile_key'))
args.append(kwargs.pop("profile_key"))
except KeyError:
pass
# at this point, kwargs should be empty
if kwargs:
log.warning("unexpected keyword arguments, they will be ignored: {}".format(kwargs))
log.warning(
"unexpected keyword arguments, they will be ignored: {}".format(
kwargs
)
)
elif len(args) >= 2 and callable(args[-1]) and callable(args[-2]):
async_ = True
_errback = args.pop()
@ -136,9 +149,11 @@ class bridge:
method = getattr(self.db_plugin_iface, name)
if async_:
kwargs['timeout'] = const_TIMEOUT
kwargs['reply_handler'] = _callback
kwargs['error_handler'] = lambda err: _errback(dbus_to_bridge_exception(err))
kwargs["timeout"] = const_TIMEOUT
kwargs["reply_handler"] = _callback
kwargs["error_handler"] = lambda err: _errback(
dbus_to_bridge_exception(err)
)
try:
return method(*args, **kwargs)
@ -158,17 +173,21 @@ class bridge:
return get_plugin_method
##METHODS_PART##
class AIOBridge(bridge):
def register_signal(self, functionName, handler, iface="core"):
loop = asyncio.get_running_loop()
async_handler = lambda *args: asyncio.run_coroutine_threadsafe(handler(*args), loop)
async_handler = lambda *args: asyncio.run_coroutine_threadsafe(
handler(*args), loop
)
return super().register_signal(functionName, async_handler, iface)
def __getattribute__(self, name):
""" usual __getattribute__ if the method exists, else try to find a plugin method """
"""usual __getattribute__ if the method exists, else try to find a plugin method"""
try:
return object.__getattribute__(self, name)
except AttributeError:
@ -178,16 +197,18 @@ class AIOBridge(bridge):
fut = loop.create_future()
method = getattr(self.db_plugin_iface, name)
reply_handler = lambda ret=None: loop.call_soon_threadsafe(
fut.set_result, ret)
fut.set_result, ret
)
error_handler = lambda err: loop.call_soon_threadsafe(
fut.set_exception, dbus_to_bridge_exception(err))
fut.set_exception, dbus_to_bridge_exception(err)
)
try:
method(
*args,
**kwargs,
timeout=const_TIMEOUT,
reply_handler=reply_handler,
error_handler=error_handler
error_handler=error_handler,
)
except ValueError as e:
if e.args[0].startswith("Unable to guess signature"):
@ -202,7 +223,7 @@ class AIOBridge(bridge):
**kwargs,
timeout=const_TIMEOUT,
reply_handler=reply_handler,
error_handler=error_handler
error_handler=error_handler,
)
else:
@ -216,8 +237,9 @@ class AIOBridge(bridge):
fut = loop.create_future()
super().bridge_connect(
callback=lambda: loop.call_soon_threadsafe(fut.set_result, None),
errback=lambda e: loop.call_soon_threadsafe(fut.set_exception, e)
errback=lambda e: loop.call_soon_threadsafe(fut.set_exception, e),
)
return fut
##ASYNC_METHODS_PART##

View file

@ -48,9 +48,11 @@ class EmbeddedConstructor(base_constructor.Constructor):
def core_completion_method(self, completion, function, default, arg_doc, async_):
completion.update(
{
"debug": ""
if not self.args.debug
else 'log.debug ("%s")\n%s' % (completion["name"], 8 * " "),
"debug": (
""
if not self.args.debug
else 'log.debug ("%s")\n%s' % (completion["name"], 8 * " ")
),
"args_result": self.get_arguments(function["sig_in"], name=arg_doc),
"args_comma": ", " if function["sig_in"] else "",
}
@ -60,9 +62,8 @@ class EmbeddedConstructor(base_constructor.Constructor):
completion["cb_or_lambda"] = (
"callback" if function["sig_out"] else "lambda __: callback()"
)
completion[
"ret_routine"
] = """\
completion["ret_routine"] = (
"""\
d = self._methods_cbs["{name}"]({args_result})
if callback is not None:
d.addCallback({cb_or_lambda})
@ -72,13 +73,13 @@ class EmbeddedConstructor(base_constructor.Constructor):
d.addErrback(errback)
return d
""".format(
**completion
**completion
)
)
else:
completion["ret_or_nothing"] = "ret" if function["sig_out"] else ""
completion[
"ret_routine"
] = """\
completion["ret_routine"] = (
"""\
try:
ret = self._methods_cbs["{name}"]({args_result})
except Exception as e:
@ -91,7 +92,8 @@ class EmbeddedConstructor(base_constructor.Constructor):
return ret
else:
callback({ret_or_nothing})""".format(
**completion
**completion
)
)
def core_completion_signal(self, completion, function, default, arg_doc, async_):

View file

@ -85,7 +85,9 @@ class _Bridge(object):
else:
cb(*args, **kwargs)
def add_method(self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}):
def add_method(
self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}
):
# FIXME: doc parameter is kept only temporary, the time to remove it from calls
log.debug("Adding method [{}] to embedded bridge".format(name))
self.register_method(name, method)

View file

@ -108,21 +108,21 @@ class MediawikiConstructor(base_constructor.Constructor):
function["sig_out"],
)
completion = {
"signature": signature_signal
if function["type"] == "signal"
else signature_method,
"signature": (
signature_signal if function["type"] == "signal" else signature_method
),
"sig_out": function["sig_out"] or "",
"category": function["category"],
"name": section,
"doc": self.get_doc(section) or "FIXME: No description available",
"async": async_msg if "async" in self.getFlags(section) else "",
"deprecated": deprecated_msg
if "deprecated" in self.getFlags(section)
else "",
"deprecated": (
deprecated_msg if "deprecated" in self.getFlags(section) else ""
),
"parameters": self._wiki_parameter(section, function["sig_in"]),
"return": self._wiki_return(section)
if function["type"] == "method"
else "",
"return": (
self._wiki_return(section) if function["type"] == "method" else ""
),
}
dest = signals_part if function["type"] == "signal" else methods_part

View file

@ -61,11 +61,13 @@ class pbConstructor(base_constructor.Constructor):
{
"args_comma": ", " if function["sig_in"] else "",
"args_no_def": self.get_arguments(function["sig_in"], name=arg_doc),
"callback": "callback"
if function["sig_out"]
else "lambda __: callback()",
"debug": ""
if not self.args.debug
else 'log.debug ("%s")\n%s' % (completion["name"], 8 * " "),
"callback": (
"callback" if function["sig_out"] else "lambda __: callback()"
),
"debug": (
""
if not self.args.debug
else 'log.debug ("%s")\n%s' % (completion["name"], 8 * " ")
),
}
)

View file

@ -99,6 +99,7 @@ class PBRoot(pb.Root):
del self.signals_paused
log.debug("bridge signals have been reactivated")
##METHODS_PART##
@ -136,7 +137,7 @@ class bridge(object):
#  self.root.register_method(name, callback)
def add_method(
self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}
self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}
):
"""Dynamically add a method to PB bridge"""
# FIXME: doc parameter is kept only temporary, the time to remove it from calls
@ -163,4 +164,5 @@ class bridge(object):
"""
self.root._bridge_reactivate_signals()
##SIGNALS_PART##

View file

@ -48,9 +48,7 @@ class SignalsHandler(pb.Referenceable):
pass
else:
raise exceptions.InternalError(
"{name} signal handler has been registered twice".format(
name=method_name
)
"{name} signal handler has been registered twice".format(name=method_name)
)
setattr(self, method_name, handler)
@ -70,8 +68,7 @@ class bridge(object):
"""Convert Failure to BridgeException"""
ori_errback(
BridgeException(
name=failure_.type.decode('utf-8'),
message=str(failure_.value)
name=failure_.type.decode("utf-8"), message=str(failure_.value)
)
)
@ -167,11 +164,13 @@ class bridge(object):
##METHODS_PART##
class AIOSignalsHandler(SignalsHandler):
def register_signal(self, name, handler, iface="core"):
async_handler = lambda *args, **kwargs: defer.Deferred.fromFuture(
asyncio.ensure_future(handler(*args, **kwargs)))
asyncio.ensure_future(handler(*args, **kwargs))
)
return super().register_signal(name, async_handler, iface)
@ -183,9 +182,8 @@ class AIOBridge(bridge):
def _errback(self, failure_):
"""Convert Failure to BridgeException"""
raise BridgeException(
name=failure_.type.decode('utf-8'),
message=str(failure_.value)
)
name=failure_.type.decode("utf-8"), message=str(failure_.value)
)
def call(self, name, *args, **kwargs):
d = self.root.callRemote(name, *args, *kwargs)
@ -196,4 +194,5 @@ class AIOBridge(bridge):
d = super().bridge_connect(callback=None, errback=None)
return await d.asFuture(asyncio.get_event_loop())
##ASYNC_METHODS_PART##

View file

@ -31,10 +31,8 @@ log = getLogger(__name__)
# Interface prefix
const_INT_PREFIX = config.config_get(
config.parse_main_conf(),
"",
"bridge_dbus_int_prefix",
"org.libervia.Libervia")
config.parse_main_conf(), "", "bridge_dbus_int_prefix", "org.libervia.Libervia"
)
const_ERROR_PREFIX = const_INT_PREFIX + ".error"
const_OBJ_PATH = "/org/libervia/Libervia/bridge"
const_CORE_SUFFIX = ".core"
@ -88,100 +86,104 @@ class DBusObject(objects.DBusObject):
core_iface = DBusInterface(
const_INT_PREFIX + const_CORE_SUFFIX,
Method('action_launch', arguments='sss', returns='s'),
Method('actions_get', arguments='s', returns='a(ssi)'),
Method('config_get', arguments='ss', returns='s'),
Method('connect', arguments='ssa{ss}', returns='b'),
Method('contact_add', arguments='ss', returns=''),
Method('contact_del', arguments='ss', returns=''),
Method('contact_get', arguments='ss', returns='(a{ss}as)'),
Method('contact_update', arguments='ssass', returns=''),
Method('contacts_get', arguments='s', returns='a(sa{ss}as)'),
Method('contacts_get_from_group', arguments='ss', returns='as'),
Method('devices_infos_get', arguments='ss', returns='s'),
Method('disco_find_by_features', arguments='asa(ss)bbbbbs', returns='(a{sa(sss)}a{sa(sss)}a{sa(sss)})'),
Method('disco_infos', arguments='ssbs', returns='(asa(sss)a{sa(a{ss}as)})'),
Method('disco_items', arguments='ssbs', returns='a(sss)'),
Method('disconnect', arguments='s', returns=''),
Method('encryption_namespace_get', arguments='s', returns='s'),
Method('encryption_plugins_get', arguments='', returns='s'),
Method('encryption_trust_ui_get', arguments='sss', returns='s'),
Method('entities_data_get', arguments='asass', returns='a{sa{ss}}'),
Method('entity_data_get', arguments='sass', returns='a{ss}'),
Method('features_get', arguments='s', returns='a{sa{ss}}'),
Method('history_get', arguments='ssiba{ss}s', returns='a(sdssa{ss}a{ss}ss)'),
Method('image_check', arguments='s', returns='s'),
Method('image_convert', arguments='ssss', returns='s'),
Method('image_generate_preview', arguments='ss', returns='s'),
Method('image_resize', arguments='sii', returns='s'),
Method('init_pre_script', arguments='', returns=''),
Method('is_connected', arguments='s', returns='b'),
Method('main_resource_get', arguments='ss', returns='s'),
Method('menu_help_get', arguments='ss', returns='s'),
Method('menu_launch', arguments='sasa{ss}is', returns='a{ss}'),
Method('menus_get', arguments='si', returns='a(ssasasa{ss})'),
Method('message_encryption_get', arguments='ss', returns='s'),
Method('message_encryption_start', arguments='ssbs', returns=''),
Method('message_encryption_stop', arguments='ss', returns=''),
Method('message_send', arguments='sa{ss}a{ss}sss', returns=''),
Method('namespaces_get', arguments='', returns='a{ss}'),
Method('notification_add', arguments='ssssbbsdss', returns=''),
Method('notification_delete', arguments='sbs', returns=''),
Method('notifications_expired_clean', arguments='ds', returns=''),
Method('notifications_get', arguments='ss', returns='s'),
Method('param_get_a', arguments='ssss', returns='s'),
Method('param_get_a_async', arguments='sssis', returns='s'),
Method('param_set', arguments='sssis', returns=''),
Method('param_ui_get', arguments='isss', returns='s'),
Method('params_categories_get', arguments='', returns='as'),
Method('params_register_app', arguments='sis', returns=''),
Method('params_template_load', arguments='s', returns='b'),
Method('params_template_save', arguments='s', returns='b'),
Method('params_values_from_category_get_async', arguments='sisss', returns='a{ss}'),
Method('presence_set', arguments='ssa{ss}s', returns=''),
Method('presence_statuses_get', arguments='s', returns='a{sa{s(sia{ss})}}'),
Method('private_data_delete', arguments='sss', returns=''),
Method('private_data_get', arguments='sss', returns='s'),
Method('private_data_set', arguments='ssss', returns=''),
Method('profile_create', arguments='sss', returns=''),
Method('profile_delete_async', arguments='s', returns=''),
Method('profile_is_session_started', arguments='s', returns='b'),
Method('profile_name_get', arguments='s', returns='s'),
Method('profile_set_default', arguments='s', returns=''),
Method('profile_start_session', arguments='ss', returns='b'),
Method('profiles_list_get', arguments='bb', returns='as'),
Method('progress_get', arguments='ss', returns='a{ss}'),
Method('progress_get_all', arguments='s', returns='a{sa{sa{ss}}}'),
Method('progress_get_all_metadata', arguments='s', returns='a{sa{sa{ss}}}'),
Method('ready_get', arguments='', returns=''),
Method('roster_resync', arguments='s', returns=''),
Method('session_infos_get', arguments='s', returns='a{ss}'),
Method('sub_waiting_get', arguments='s', returns='a{ss}'),
Method('subscription', arguments='sss', returns=''),
Method('version_get', arguments='', returns='s'),
Signal('_debug', 'sa{ss}s'),
Signal('action_new', 'ssis'),
Signal('connected', 'ss'),
Signal('contact_deleted', 'ss'),
Signal('contact_new', 'sa{ss}ass'),
Signal('disconnected', 's'),
Signal('entity_data_updated', 'ssss'),
Signal('message_encryption_started', 'sss'),
Signal('message_encryption_stopped', 'sa{ss}s'),
Signal('message_new', 'sdssa{ss}a{ss}sss'),
Signal('message_update', 'ssss'),
Signal('notification_deleted', 'ss'),
Signal('notification_new', 'sdssssbidss'),
Signal('param_update', 'ssss'),
Signal('presence_update', 'ssia{ss}s'),
Signal('progress_error', 'sss'),
Signal('progress_finished', 'sa{ss}s'),
Signal('progress_started', 'sa{ss}s'),
Signal('subscribe', 'sss'),
)
plugin_iface = DBusInterface(
const_INT_PREFIX + const_PLUGIN_SUFFIX
Method("action_launch", arguments="sss", returns="s"),
Method("actions_get", arguments="s", returns="a(ssi)"),
Method("config_get", arguments="ss", returns="s"),
Method("connect", arguments="ssa{ss}", returns="b"),
Method("contact_add", arguments="ss", returns=""),
Method("contact_del", arguments="ss", returns=""),
Method("contact_get", arguments="ss", returns="(a{ss}as)"),
Method("contact_update", arguments="ssass", returns=""),
Method("contacts_get", arguments="s", returns="a(sa{ss}as)"),
Method("contacts_get_from_group", arguments="ss", returns="as"),
Method("devices_infos_get", arguments="ss", returns="s"),
Method(
"disco_find_by_features",
arguments="asa(ss)bbbbbs",
returns="(a{sa(sss)}a{sa(sss)}a{sa(sss)})",
),
Method("disco_infos", arguments="ssbs", returns="(asa(sss)a{sa(a{ss}as)})"),
Method("disco_items", arguments="ssbs", returns="a(sss)"),
Method("disconnect", arguments="s", returns=""),
Method("encryption_namespace_get", arguments="s", returns="s"),
Method("encryption_plugins_get", arguments="", returns="s"),
Method("encryption_trust_ui_get", arguments="sss", returns="s"),
Method("entities_data_get", arguments="asass", returns="a{sa{ss}}"),
Method("entity_data_get", arguments="sass", returns="a{ss}"),
Method("features_get", arguments="s", returns="a{sa{ss}}"),
Method("history_get", arguments="ssiba{ss}s", returns="a(sdssa{ss}a{ss}ss)"),
Method("image_check", arguments="s", returns="s"),
Method("image_convert", arguments="ssss", returns="s"),
Method("image_generate_preview", arguments="ss", returns="s"),
Method("image_resize", arguments="sii", returns="s"),
Method("init_pre_script", arguments="", returns=""),
Method("is_connected", arguments="s", returns="b"),
Method("main_resource_get", arguments="ss", returns="s"),
Method("menu_help_get", arguments="ss", returns="s"),
Method("menu_launch", arguments="sasa{ss}is", returns="a{ss}"),
Method("menus_get", arguments="si", returns="a(ssasasa{ss})"),
Method("message_encryption_get", arguments="ss", returns="s"),
Method("message_encryption_start", arguments="ssbs", returns=""),
Method("message_encryption_stop", arguments="ss", returns=""),
Method("message_send", arguments="sa{ss}a{ss}sss", returns=""),
Method("namespaces_get", arguments="", returns="a{ss}"),
Method("notification_add", arguments="ssssbbsdss", returns=""),
Method("notification_delete", arguments="sbs", returns=""),
Method("notifications_expired_clean", arguments="ds", returns=""),
Method("notifications_get", arguments="ss", returns="s"),
Method("param_get_a", arguments="ssss", returns="s"),
Method("param_get_a_async", arguments="sssis", returns="s"),
Method("param_set", arguments="sssis", returns=""),
Method("param_ui_get", arguments="isss", returns="s"),
Method("params_categories_get", arguments="", returns="as"),
Method("params_register_app", arguments="sis", returns=""),
Method("params_template_load", arguments="s", returns="b"),
Method("params_template_save", arguments="s", returns="b"),
Method(
"params_values_from_category_get_async", arguments="sisss", returns="a{ss}"
),
Method("presence_set", arguments="ssa{ss}s", returns=""),
Method("presence_statuses_get", arguments="s", returns="a{sa{s(sia{ss})}}"),
Method("private_data_delete", arguments="sss", returns=""),
Method("private_data_get", arguments="sss", returns="s"),
Method("private_data_set", arguments="ssss", returns=""),
Method("profile_create", arguments="sss", returns=""),
Method("profile_delete_async", arguments="s", returns=""),
Method("profile_is_session_started", arguments="s", returns="b"),
Method("profile_name_get", arguments="s", returns="s"),
Method("profile_set_default", arguments="s", returns=""),
Method("profile_start_session", arguments="ss", returns="b"),
Method("profiles_list_get", arguments="bb", returns="as"),
Method("progress_get", arguments="ss", returns="a{ss}"),
Method("progress_get_all", arguments="s", returns="a{sa{sa{ss}}}"),
Method("progress_get_all_metadata", arguments="s", returns="a{sa{sa{ss}}}"),
Method("ready_get", arguments="", returns=""),
Method("roster_resync", arguments="s", returns=""),
Method("session_infos_get", arguments="s", returns="a{ss}"),
Method("sub_waiting_get", arguments="s", returns="a{ss}"),
Method("subscription", arguments="sss", returns=""),
Method("version_get", arguments="", returns="s"),
Signal("_debug", "sa{ss}s"),
Signal("action_new", "ssis"),
Signal("connected", "ss"),
Signal("contact_deleted", "ss"),
Signal("contact_new", "sa{ss}ass"),
Signal("disconnected", "s"),
Signal("entity_data_updated", "ssss"),
Signal("message_encryption_started", "sss"),
Signal("message_encryption_stopped", "sa{ss}s"),
Signal("message_new", "sdssa{ss}a{ss}sss"),
Signal("message_update", "ssss"),
Signal("notification_deleted", "ss"),
Signal("notification_new", "sdssssbidss"),
Signal("param_update", "ssss"),
Signal("presence_update", "ssia{ss}s"),
Signal("progress_error", "sss"),
Signal("progress_finished", "sa{ss}s"),
Signal("progress_started", "sa{ss}s"),
Signal("subscribe", "sss"),
)
plugin_iface = DBusInterface(const_INT_PREFIX + const_PLUGIN_SUFFIX)
dbusInterfaces = [core_iface, plugin_iface]
@ -213,7 +215,7 @@ class DBusObject(objects.DBusObject):
def dbus_config_get(self, section, name):
return self._callback("config_get", section, name)
def dbus_connect(self, profile_key="@DEFAULT@", password='', options={}):
def dbus_connect(self, profile_key="@DEFAULT@", password="", options={}):
return self._callback("connect", profile_key, password, options)
def dbus_contact_add(self, entity_jid, profile_key="@DEFAULT@"):
@ -237,13 +239,37 @@ class DBusObject(objects.DBusObject):
def dbus_devices_infos_get(self, bare_jid, profile_key):
return self._callback("devices_infos_get", bare_jid, profile_key)
def dbus_disco_find_by_features(self, namespaces, identities, bare_jid=False, service=True, roster=True, own_jid=True, local_device=False, profile_key="@DEFAULT@"):
return self._callback("disco_find_by_features", namespaces, identities, bare_jid, service, roster, own_jid, local_device, profile_key)
def dbus_disco_find_by_features(
self,
namespaces,
identities,
bare_jid=False,
service=True,
roster=True,
own_jid=True,
local_device=False,
profile_key="@DEFAULT@",
):
return self._callback(
"disco_find_by_features",
namespaces,
identities,
bare_jid,
service,
roster,
own_jid,
local_device,
profile_key,
)
def dbus_disco_infos(self, entity_jid, node=u'', use_cache=True, profile_key="@DEFAULT@"):
def dbus_disco_infos(
self, entity_jid, node="", use_cache=True, profile_key="@DEFAULT@"
):
return self._callback("disco_infos", entity_jid, node, use_cache, profile_key)
def dbus_disco_items(self, entity_jid, node=u'', use_cache=True, profile_key="@DEFAULT@"):
def dbus_disco_items(
self, entity_jid, node="", use_cache=True, profile_key="@DEFAULT@"
):
return self._callback("disco_items", entity_jid, node, use_cache, profile_key)
def dbus_disconnect(self, profile_key="@DEFAULT@"):
@ -252,8 +278,12 @@ class DBusObject(objects.DBusObject):
def dbus_encryption_namespace_get(self, arg_0):
return self._callback("encryption_namespace_get", arg_0)
def dbus_encryption_plugins_get(self, ):
return self._callback("encryption_plugins_get", )
def dbus_encryption_plugins_get(
self,
):
return self._callback(
"encryption_plugins_get",
)
def dbus_encryption_trust_ui_get(self, to_jid, namespace, profile_key):
return self._callback("encryption_trust_ui_get", to_jid, namespace, profile_key)
@ -267,8 +297,12 @@ class DBusObject(objects.DBusObject):
def dbus_features_get(self, profile_key):
return self._callback("features_get", profile_key)
def dbus_history_get(self, from_jid, to_jid, limit, between=True, filters='', profile="@NONE@"):
return self._callback("history_get", from_jid, to_jid, limit, between, filters, profile)
def dbus_history_get(
self, from_jid, to_jid, limit, between=True, filters="", profile="@NONE@"
):
return self._callback(
"history_get", from_jid, to_jid, limit, between, filters, profile
)
def dbus_image_check(self, arg_0):
return self._callback("image_check", arg_0)
@ -282,8 +316,12 @@ class DBusObject(objects.DBusObject):
def dbus_image_resize(self, image_path, width, height):
return self._callback("image_resize", image_path, width, height)
def dbus_init_pre_script(self, ):
return self._callback("init_pre_script", )
def dbus_init_pre_script(
self,
):
return self._callback(
"init_pre_script",
)
def dbus_is_connected(self, profile_key="@DEFAULT@"):
return self._callback("is_connected", profile_key)
@ -295,7 +333,9 @@ class DBusObject(objects.DBusObject):
return self._callback("menu_help_get", menu_id, language)
def dbus_menu_launch(self, menu_type, path, data, security_limit, profile_key):
return self._callback("menu_launch", menu_type, path, data, security_limit, profile_key)
return self._callback(
"menu_launch", menu_type, path, data, security_limit, profile_key
)
def dbus_menus_get(self, language, security_limit):
return self._callback("menus_get", language, security_limit)
@ -303,20 +343,62 @@ class DBusObject(objects.DBusObject):
def dbus_message_encryption_get(self, to_jid, profile_key):
return self._callback("message_encryption_get", to_jid, profile_key)
def dbus_message_encryption_start(self, to_jid, namespace='', replace=False, profile_key="@NONE@"):
return self._callback("message_encryption_start", to_jid, namespace, replace, profile_key)
def dbus_message_encryption_start(
self, to_jid, namespace="", replace=False, profile_key="@NONE@"
):
return self._callback(
"message_encryption_start", to_jid, namespace, replace, profile_key
)
def dbus_message_encryption_stop(self, to_jid, profile_key):
return self._callback("message_encryption_stop", to_jid, profile_key)
def dbus_message_send(self, to_jid, message, subject={}, mess_type="auto", extra={}, profile_key="@NONE@"):
return self._callback("message_send", to_jid, message, subject, mess_type, extra, profile_key)
def dbus_message_send(
self,
to_jid,
message,
subject={},
mess_type="auto",
extra={},
profile_key="@NONE@",
):
return self._callback(
"message_send", to_jid, message, subject, mess_type, extra, profile_key
)
def dbus_namespaces_get(self, ):
return self._callback("namespaces_get", )
def dbus_namespaces_get(
self,
):
return self._callback(
"namespaces_get",
)
def dbus_notification_add(self, type_, body_plain, body_rich, title, is_global, requires_action, arg_6, priority, expire_at, extra):
return self._callback("notification_add", type_, body_plain, body_rich, title, is_global, requires_action, arg_6, priority, expire_at, extra)
def dbus_notification_add(
self,
type_,
body_plain,
body_rich,
title,
is_global,
requires_action,
arg_6,
priority,
expire_at,
extra,
):
return self._callback(
"notification_add",
type_,
body_plain,
body_rich,
title,
is_global,
requires_action,
arg_6,
priority,
expire_at,
extra,
)
def dbus_notification_delete(self, id_, is_global, profile_key):
return self._callback("notification_delete", id_, is_global, profile_key)
@ -327,22 +409,43 @@ class DBusObject(objects.DBusObject):
def dbus_notifications_get(self, filters, profile_key):
return self._callback("notifications_get", filters, profile_key)
def dbus_param_get_a(self, name, category, attribute="value", profile_key="@DEFAULT@"):
def dbus_param_get_a(
self, name, category, attribute="value", profile_key="@DEFAULT@"
):
return self._callback("param_get_a", name, category, attribute, profile_key)
def dbus_param_get_a_async(self, name, category, attribute="value", security_limit=-1, profile_key="@DEFAULT@"):
return self._callback("param_get_a_async", name, category, attribute, security_limit, profile_key)
def dbus_param_get_a_async(
self,
name,
category,
attribute="value",
security_limit=-1,
profile_key="@DEFAULT@",
):
return self._callback(
"param_get_a_async", name, category, attribute, security_limit, profile_key
)
def dbus_param_set(self, name, value, category, security_limit=-1, profile_key="@DEFAULT@"):
return self._callback("param_set", name, value, category, security_limit, profile_key)
def dbus_param_set(
self, name, value, category, security_limit=-1, profile_key="@DEFAULT@"
):
return self._callback(
"param_set", name, value, category, security_limit, profile_key
)
def dbus_param_ui_get(self, security_limit=-1, app='', extra='', profile_key="@DEFAULT@"):
def dbus_param_ui_get(
self, security_limit=-1, app="", extra="", profile_key="@DEFAULT@"
):
return self._callback("param_ui_get", security_limit, app, extra, profile_key)
def dbus_params_categories_get(self, ):
return self._callback("params_categories_get", )
def dbus_params_categories_get(
self,
):
return self._callback(
"params_categories_get",
)
def dbus_params_register_app(self, xml, security_limit=-1, app=''):
def dbus_params_register_app(self, xml, security_limit=-1, app=""):
return self._callback("params_register_app", xml, security_limit, app)
def dbus_params_template_load(self, filename):
@ -351,10 +454,19 @@ class DBusObject(objects.DBusObject):
def dbus_params_template_save(self, filename):
return self._callback("params_template_save", filename)
def dbus_params_values_from_category_get_async(self, category, security_limit=-1, app="", extra="", profile_key="@DEFAULT@"):
return self._callback("params_values_from_category_get_async", category, security_limit, app, extra, profile_key)
def dbus_params_values_from_category_get_async(
self, category, security_limit=-1, app="", extra="", profile_key="@DEFAULT@"
):
return self._callback(
"params_values_from_category_get_async",
category,
security_limit,
app,
extra,
profile_key,
)
def dbus_presence_set(self, to_jid='', show='', statuses={}, profile_key="@DEFAULT@"):
def dbus_presence_set(self, to_jid="", show="", statuses={}, profile_key="@DEFAULT@"):
return self._callback("presence_set", to_jid, show, statuses, profile_key)
def dbus_presence_statuses_get(self, profile_key="@DEFAULT@"):
@ -369,7 +481,7 @@ class DBusObject(objects.DBusObject):
def dbus_private_data_set(self, namespace, key, data, profile_key):
return self._callback("private_data_set", namespace, key, data, profile_key)
def dbus_profile_create(self, profile, password='', component=''):
def dbus_profile_create(self, profile, password="", component=""):
return self._callback("profile_create", profile, password, component)
def dbus_profile_delete_async(self, profile):
@ -384,7 +496,7 @@ class DBusObject(objects.DBusObject):
def dbus_profile_set_default(self, profile):
return self._callback("profile_set_default", profile)
def dbus_profile_start_session(self, password='', profile_key="@DEFAULT@"):
def dbus_profile_start_session(self, password="", profile_key="@DEFAULT@"):
return self._callback("profile_start_session", password, profile_key)
def dbus_profiles_list_get(self, clients=True, components=False):
@ -399,8 +511,12 @@ class DBusObject(objects.DBusObject):
def dbus_progress_get_all_metadata(self, profile):
return self._callback("progress_get_all_metadata", profile)
def dbus_ready_get(self, ):
return self._callback("ready_get", )
def dbus_ready_get(
self,
):
return self._callback(
"ready_get",
)
def dbus_roster_resync(self, profile_key="@DEFAULT@"):
return self._callback("roster_resync", profile_key)
@ -414,8 +530,12 @@ class DBusObject(objects.DBusObject):
def dbus_subscription(self, sub_type, entity, profile_key="@DEFAULT@"):
return self._callback("subscription", sub_type, entity, profile_key)
def dbus_version_get(self, ):
return self._callback("version_get", )
def dbus_version_get(
self,
):
return self._callback(
"version_get",
)
class bridge:
@ -462,13 +582,39 @@ class bridge:
self._obj.emitSignal("entity_data_updated", jid, name, value, profile)
def message_encryption_started(self, to_jid, encryption_data, profile_key):
self._obj.emitSignal("message_encryption_started", to_jid, encryption_data, profile_key)
self._obj.emitSignal(
"message_encryption_started", to_jid, encryption_data, profile_key
)
def message_encryption_stopped(self, to_jid, encryption_data, profile_key):
self._obj.emitSignal("message_encryption_stopped", to_jid, encryption_data, profile_key)
self._obj.emitSignal(
"message_encryption_stopped", to_jid, encryption_data, profile_key
)
def message_new(self, uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile):
self._obj.emitSignal("message_new", uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile)
def message_new(
self,
uid,
timestamp,
from_jid,
to_jid,
message,
subject,
mess_type,
extra,
profile,
):
self._obj.emitSignal(
"message_new",
uid,
timestamp,
from_jid,
to_jid,
message,
subject,
mess_type,
extra,
profile,
)
def message_update(self, uid, message_type, message_data, profile):
self._obj.emitSignal("message_update", uid, message_type, message_data, profile)
@ -476,14 +622,42 @@ class bridge:
def notification_deleted(self, id, profile):
self._obj.emitSignal("notification_deleted", id, profile)
def notification_new(self, id, timestamp, type, body_plain, body_rich, title, requires_action, priority, expire_at, extra, profile):
self._obj.emitSignal("notification_new", id, timestamp, type, body_plain, body_rich, title, requires_action, priority, expire_at, extra, profile)
def notification_new(
self,
id,
timestamp,
type,
body_plain,
body_rich,
title,
requires_action,
priority,
expire_at,
extra,
profile,
):
self._obj.emitSignal(
"notification_new",
id,
timestamp,
type,
body_plain,
body_rich,
title,
requires_action,
priority,
expire_at,
extra,
profile,
)
def param_update(self, name, value, category, profile):
self._obj.emitSignal("param_update", name, value, category, profile)
def presence_update(self, entity_jid, show, priority, statuses, profile):
self._obj.emitSignal("presence_update", entity_jid, show, priority, statuses, profile)
self._obj.emitSignal(
"presence_update", entity_jid, show, priority, statuses, profile
)
def progress_error(self, id, error, profile):
self._obj.emitSignal("progress_error", id, error, profile)
@ -505,7 +679,7 @@ class bridge:
self._obj.emitSignal(name, *args)
def add_method(
self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}
self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}
):
"""Dynamically add a method to D-Bus bridge"""
# FIXME: doc parameter is kept only temporary, the time to remove it from calls
@ -513,10 +687,12 @@ class bridge:
self._obj.plugin_iface.addMethod(
Method(name, arguments=in_sign, returns=out_sign)
)
# we have to create a method here instead of using partialmethod, because txdbus
# uses __func__ which doesn't work with partialmethod
def caller(self_, *args, **kwargs):
return self_._callback(name, *args, **kwargs)
setattr(self._obj, f"dbus_{name}", MethodType(caller, self._obj))
self.register_method(name, method)
@ -524,4 +700,4 @@ class bridge:
"""Dynamically add a signal to D-Bus bridge"""
log.debug(f"Adding signal {name!r} to D-Bus bridge")
self._obj.plugin_iface.addSignal(Signal(name, signature))
setattr(bridge, name, partialmethod(bridge.emit_signal, name))
setattr(bridge, name, partialmethod(bridge.emit_signal, name))

View file

@ -99,6 +99,7 @@ class PBRoot(pb.Root):
del self.signals_paused
log.debug("bridge signals have been reactivated")
##METHODS_PART##
@ -136,7 +137,7 @@ class bridge(object):
#  self.root.register_method(name, callback)
def add_method(
self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}
self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}
):
"""Dynamically add a method to PB bridge"""
# FIXME: doc parameter is kept only temporary, the time to remove it from calls
@ -185,13 +186,39 @@ class bridge(object):
self.send_signal("entity_data_updated", jid, name, value, profile)
def message_encryption_started(self, to_jid, encryption_data, profile_key):
self.send_signal("message_encryption_started", to_jid, encryption_data, profile_key)
self.send_signal(
"message_encryption_started", to_jid, encryption_data, profile_key
)
def message_encryption_stopped(self, to_jid, encryption_data, profile_key):
self.send_signal("message_encryption_stopped", to_jid, encryption_data, profile_key)
self.send_signal(
"message_encryption_stopped", to_jid, encryption_data, profile_key
)
def message_new(self, uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile):
self.send_signal("message_new", uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile)
def message_new(
self,
uid,
timestamp,
from_jid,
to_jid,
message,
subject,
mess_type,
extra,
profile,
):
self.send_signal(
"message_new",
uid,
timestamp,
from_jid,
to_jid,
message,
subject,
mess_type,
extra,
profile,
)
def message_update(self, uid, message_type, message_data, profile):
self.send_signal("message_update", uid, message_type, message_data, profile)
@ -199,8 +226,34 @@ class bridge(object):
def notification_deleted(self, id, profile):
self.send_signal("notification_deleted", id, profile)
def notification_new(self, id, timestamp, type, body_plain, body_rich, title, requires_action, priority, expire_at, extra, profile):
self.send_signal("notification_new", id, timestamp, type, body_plain, body_rich, title, requires_action, priority, expire_at, extra, profile)
def notification_new(
self,
id,
timestamp,
type,
body_plain,
body_rich,
title,
requires_action,
priority,
expire_at,
extra,
profile,
):
self.send_signal(
"notification_new",
id,
timestamp,
type,
body_plain,
body_rich,
title,
requires_action,
priority,
expire_at,
extra,
profile,
)
def param_update(self, name, value, category, profile):
self.send_signal("param_update", name, value, category, profile)

View file

@ -46,9 +46,7 @@ class Const(object):
APP_NAME_ALT = "Libervia"
APP_NAME_FILE = "libervia"
APP_NAME_FULL = f"{APP_NAME} ({APP_COMPONENT})"
APP_VERSION = (
backend.__version__
)
APP_VERSION = backend.__version__
APP_RELEASE_NAME = "La Ruche"
APP_URL = "https://libervia.org"
@ -117,8 +115,8 @@ class Const(object):
## Roster jids selection ##
PUBLIC = "PUBLIC"
ALL = (
"ALL"
) # ALL means all known contacts, while PUBLIC means everybody, known or not
"ALL" # ALL means all known contacts, while PUBLIC means everybody, known or not
)
GROUP = "GROUP"
JID = "JID"
@ -226,9 +224,7 @@ class Const(object):
PI_IMPORT_NAME = "import_name"
PI_MAIN = "main"
PI_HANDLER = "handler"
PI_TYPE = (
"type"
) #  FIXME: should be types, and should handle single unicode type or tuple of types (e.g. "blog" and "import")
PI_TYPE = "type" #  FIXME: should be types, and should handle single unicode type or tuple of types (e.g. "blog" and "import")
PI_MODES = "modes"
PI_PROTOCOLS = "protocols"
PI_DEPENDENCIES = "dependencies"
@ -405,14 +401,13 @@ class Const(object):
KEY_ATTACHMENTS_PREVIEW = "preview"
KEY_ATTACHMENTS_RESIZE = "resize"
## Common extra keys/values ##
KEY_ORDER_BY = "order_by"
KEY_USE_CACHE = "use_cache"
KEY_DECRYPT = "decrypt"
ORDER_BY_CREATION = 'creation'
ORDER_BY_MODIFICATION = 'modification'
ORDER_BY_CREATION = "creation"
ORDER_BY_MODIFICATION = "modification"
# internationalisation
DEFAULT_LOCALE = "en_GB"
@ -432,9 +427,7 @@ class Const(object):
EXIT_CONFLICT = 19 # an item already exists
EXIT_USER_CANCELLED = 20 # user cancelled action
EXIT_INTERNAL_ERROR = 111 # unexpected error
EXIT_FILE_NOT_EXE = (
126
) # a file to be executed was found, but it was not an executable utility (cf. man 1 exit)
EXIT_FILE_NOT_EXE = 126 # a file to be executed was found, but it was not an executable utility (cf. man 1 exit)
EXIT_CMD_NOT_FOUND = 127 # a utility to be executed was not found (cf. man 1 exit)
EXIT_CMD_ERROR = 127 # a utility to be executed returned an error exit code
EXIT_SIGNAL_INT = 128 # a command was interrupted by a signal (cf. man 1 exit)
@ -492,8 +485,9 @@ if (
# we don't want the very verbose jnius log when we are in DEBUG level
import logging
logging.getLogger('jnius').setLevel(logging.WARNING)
logging.getLogger('jnius.reflect').setLevel(logging.WARNING)
logging.getLogger("jnius").setLevel(logging.WARNING)
logging.getLogger("jnius.reflect").setLevel(logging.WARNING)
Environment = autoclass("android.os.Environment")
@ -518,9 +512,10 @@ if (
]
else:
import os
# we use parent of "sat" module dir as last config path, this is useful for
# per instance configurations (e.g. a dev instance and a main instance)
root_dir = dirname(dirname(backend.__file__)) + '/'
root_dir = dirname(dirname(backend.__file__)) + "/"
Const.CONFIG_PATHS = (
# /etc/_sat.conf is used for system-related settings (e.g. when media_dir
# is set by the distribution and has not reason to change, or in a Docker
@ -541,10 +536,10 @@ if (
# on recent versions of Flatpak, FLATPAK_ID is set at run time
# it seems that this is not the case on older versions,
# but FLATPAK_SANDBOX_DIR seems set then
if os.getenv('FLATPAK_ID') or os.getenv('FLATPAK_SANDBOX_DIR'):
if os.getenv("FLATPAK_ID") or os.getenv("FLATPAK_SANDBOX_DIR"):
# for Flatpak, the conf can't be set in /etc or $HOME, so we have
# to add /app
Const.CONFIG_PATHS.append('/app/')
Const.CONFIG_PATHS.append("/app/")
## Configuration ##
Const.DEFAULT_CONFIG = {
@ -564,4 +559,3 @@ if (
realpath(expanduser(path) + "sat.conf")
for path in Const.CONFIG_PATHS
]

View file

@ -34,11 +34,10 @@ class SatXMPPEntity:
server_jid: t_jid.JID
IQ: Callable[[Optional[str], Optional[int]], xmlstream.IQ]
EncryptionPlugin = namedtuple("EncryptionPlugin", ("instance",
"name",
"namespace",
"priority",
"directed"))
EncryptionPlugin = namedtuple(
"EncryptionPlugin", ("instance", "name", "namespace", "priority", "directed")
)
class EncryptionSession(TypedDict):
@ -47,21 +46,23 @@ class EncryptionSession(TypedDict):
# Incomplete types built through observation rather than code inspection.
MessageDataExtra = TypedDict(
"MessageDataExtra",
{ "encrypted": bool, "origin_id": str },
total=False
"MessageDataExtra", {"encrypted": bool, "origin_id": str}, total=False
)
MessageData = TypedDict("MessageData", {
"from": t_jid.JID,
"to": t_jid.JID,
"uid": str,
"message": Dict[str, str],
"subject": Dict[str, str],
"type": str,
"timestamp": float,
"extra": MessageDataExtra,
"ENCRYPTION": EncryptionSession,
"xml": domish.Element
}, total=False)
MessageData = TypedDict(
"MessageData",
{
"from": t_jid.JID,
"to": t_jid.JID,
"uid": str,
"message": Dict[str, str],
"subject": Dict[str, str],
"type": str,
"timestamp": float,
"extra": MessageDataExtra,
"ENCRYPTION": EncryptionSession,
"xml": domish.Element,
},
total=False,
)

View file

@ -62,6 +62,7 @@ class MissingModule(Exception):
class MissingPlugin(Exception):
"""A SàT plugin needed for a feature/method is missing"""
pass
@ -129,6 +130,7 @@ class ParsingError(ValueError):
class EncryptionError(Exception):
"""Invalid encryption"""
pass
@ -143,6 +145,7 @@ class NetworkError(Exception):
class InvalidCertificate(Exception):
"""A TLS certificate is not valid"""
pass

View file

@ -37,7 +37,6 @@ try:
)
_translators[lang].install()
except ImportError:
log.warning("gettext support disabled")

View file

@ -201,11 +201,7 @@ class Launcher:
return pid_dir / f"{self.APP_NAME_FILE}.pid"
def wait_for_service(
self,
service_host: str,
service_port: int,
timeout: int,
service_name: str
self, service_host: str, service_port: int, timeout: int, service_name: str
) -> None:
"""Waits for a network service to become available.

View file

@ -36,8 +36,8 @@ import traceback
backend = None
_loggers: Dict[str, "Logger"] = {}
handlers = {}
COLOR_START = '%(color_start)s'
COLOR_END = '%(color_end)s'
COLOR_START = "%(color_start)s"
COLOR_END = "%(color_end)s"
class Filtered(Exception):
@ -46,8 +46,9 @@ class Filtered(Exception):
class Logger:
"""High level logging class"""
fmt = None # format option as given by user (e.g. SAT_LOG_LOGGER)
filter_name = None # filter to call
fmt = None # format option as given by user (e.g. SAT_LOG_LOGGER)
filter_name = None # filter to call
post_treat = None
def __init__(self, name):
@ -72,7 +73,7 @@ class Logger:
message: object,
level: Optional[str] = None,
exc_info: _ExcInfoType = False,
**kwargs
**kwargs,
) -> None:
"""Actually log the message
@ -83,11 +84,7 @@ class Logger:
print(message)
def log(
self,
level: str,
message: object,
exc_info: _ExcInfoType = False,
**kwargs
self, level: str, message: object, exc_info: _ExcInfoType = False, **kwargs
) -> None:
"""Print message
@ -116,14 +113,18 @@ class Logger:
"""
if self.fmt is None and self.filter_name is None:
return message
record = {'name': self._name,
'message': message,
'levelname': level,
}
record = {
"name": self._name,
"message": message,
"levelname": level,
}
try:
if not self.filter_name.dict_filter(record):
raise Filtered
except (AttributeError, TypeError): # XXX: TypeError is here because of a pyjamas bug which need to be fixed (TypeError is raised instead of AttributeError)
except (
AttributeError,
TypeError,
): # XXX: TypeError is here because of a pyjamas bug which need to be fixed (TypeError is raised instead of AttributeError)
if self.filter_name is not None:
raise ValueError("Bad filter: filters must have a .filter method")
try:
@ -131,9 +132,9 @@ class Logger:
except TypeError:
return message
except KeyError as e:
if e.args[0] == 'profile':
if e.args[0] == "profile":
# XXX: %(profile)s use some magic with introspection, for debugging purpose only *DO NOT* use in production
record['profile'] = configure_cls[backend].get_profile()
record["profile"] = configure_cls[backend].get_profile()
return self.fmt % record
else:
raise e
@ -167,6 +168,7 @@ class FilterName(object):
"""
assert name_re
import re
self.name_re = re.compile(name_re)
def filter(self, record):
@ -180,10 +182,12 @@ class FilterName(object):
@param dict_record: dictionary with at list a key "name" with logger name
@return: True if message should be logged
"""
class LogRecord(object):
pass
log_record = LogRecord()
log_record.name = dict_record['name']
log_record.name = dict_record["name"]
return self.filter(log_record) == 1
@ -192,8 +196,17 @@ class ConfigureBase:
# True if color location is specified in fmt (with COLOR_START)
_color_location = False
def __init__(self, level=None, fmt=None, output=None, logger=None, colors=False,
levels_taints_dict=None, force_colors=False, backend_data=None):
def __init__(
self,
level=None,
fmt=None,
output=None,
logger=None,
colors=False,
levels_taints_dict=None,
force_colors=False,
backend_data=None,
):
"""Configure a backend
@param level: one of C.LOG_LEVELS
@ -231,19 +244,21 @@ class ConfigureBase:
if level is not None:
# we deactivate methods below level
level_idx = C.LOG_LEVELS.index(level)
def dev_null(self, msg):
pass
for _level in C.LOG_LEVELS[:level_idx]:
setattr(Logger, _level.lower(), dev_null)
def configure_format(self, fmt):
if fmt is not None:
if fmt != '%(message)s': # %(message)s is the same as None
if fmt != "%(message)s": # %(message)s is the same as None
Logger.fmt = fmt
if COLOR_START in fmt:
ConfigureBase._color_location = True
if fmt.find(COLOR_END,fmt.rfind(COLOR_START))<0:
# color_start not followed by an end, we add it
if fmt.find(COLOR_END, fmt.rfind(COLOR_START)) < 0:
# color_start not followed by an end, we add it
Logger.fmt += COLOR_END
def configure_output(self, output):
@ -265,12 +280,14 @@ class ConfigureBase:
taints = self.__class__.taints = {}
for level in C.LOG_LEVELS:
# we want use values and use constant value as default
taint_list = levels_taints_dict.get(level, C.LOG_OPT_TAINTS_DICT[1][level])
taint_list = levels_taints_dict.get(
level, C.LOG_OPT_TAINTS_DICT[1][level]
)
ansi_list = []
for elt in taint_list:
elt = elt.upper()
try:
ansi = getattr(A, 'FG_{}'.format(elt))
ansi = getattr(A, "FG_{}".format(elt))
except AttributeError:
try:
ansi = getattr(A, elt)
@ -278,13 +295,13 @@ class ConfigureBase:
# we use raw string if element is unknown
ansi = elt
ansi_list.append(ansi)
taints[level] = ''.join(ansi_list)
taints[level] = "".join(ansi_list)
def post_treatment(self):
pass
def manage_outputs(self, outputs_raw):
""" Parse output option in a backend agnostic way, and fill handlers consequently
"""Parse output option in a backend agnostic way, and fill handlers consequently
@param outputs_raw: output option as enterred in environment variable or in configuration
"""
@ -298,15 +315,19 @@ class ConfigureBase:
for output in outputs:
if not output:
continue
if output[-1] == ')':
if output[-1] == ")":
# we have options
opt_begin = output.rfind('(')
options = output[opt_begin+1:-1]
opt_begin = output.rfind("(")
options = output[opt_begin + 1 : -1]
output = output[:opt_begin]
else:
options = None
if output not in (C.LOG_OPT_OUTPUT_DEFAULT, C.LOG_OPT_OUTPUT_FILE, C.LOG_OPT_OUTPUT_MEMORY):
if output not in (
C.LOG_OPT_OUTPUT_DEFAULT,
C.LOG_OPT_OUTPUT_FILE,
C.LOG_OPT_OUTPUT_MEMORY,
):
raise ValueError("Invalid output [%s]" % output)
if output == C.LOG_OPT_OUTPUT_DEFAULT:
@ -314,20 +335,26 @@ class ConfigureBase:
handlers[output] = None
elif output == C.LOG_OPT_OUTPUT_FILE:
if not options:
ValueError("{handler} output need a path as option" .format(handle=output))
ValueError(
"{handler} output need a path as option".format(handle=output)
)
handlers.setdefault(output, []).append(options)
options = None # option are parsed, we can empty them
options = None # option are parsed, we can empty them
elif output == C.LOG_OPT_OUTPUT_MEMORY:
# we have memory handler, option can be the len limit or None
try:
limit = int(options)
options = None # option are parsed, we can empty them
options = None # option are parsed, we can empty them
except (TypeError, ValueError):
limit = C.LOG_OPT_OUTPUT_MEMORY_LIMIT
handlers[output] = limit
if options: # we should not have unparsed options
raise ValueError("options [{options}] are not supported for {handler} output".format(options=options, handler=output))
if options: # we should not have unparsed options
raise ValueError(
"options [{options}] are not supported for {handler} output".format(
options=options, handler=output
)
)
@staticmethod
def memory_get(size=None):
@ -349,13 +376,12 @@ class ConfigureBase:
try:
start = cls.taints[level]
except KeyError:
start = ''
start = ""
if cls._color_location:
return message % {'color_start': start,
'color_end': A.RESET}
return message % {"color_start": start, "color_end": A.RESET}
else:
return '%s%s%s' % (start, message, A.RESET)
return "%s%s%s" % (start, message, A.RESET)
@staticmethod
def get_profile():
@ -370,9 +396,10 @@ class ConfigureCustom(ConfigureBase):
ConfigureCustom.LOGGER_CLASS = logger_class
configure_cls = { None: ConfigureBase,
C.LOG_BACKEND_CUSTOM: ConfigureCustom
} # XXX: (key: backend, value: Configure subclass) must be filled when new backend are added
configure_cls = {
None: ConfigureBase,
C.LOG_BACKEND_CUSTOM: ConfigureCustom,
} # XXX: (key: backend, value: Configure subclass) must be filled when new backend are added
def configure(backend_, **options):
@ -391,36 +418,46 @@ def configure(backend_, **options):
except KeyError:
raise ValueError("unknown backend [{}]".format(backend))
if backend == C.LOG_BACKEND_CUSTOM:
logger_class = options.pop('logger_class')
logger_class = options.pop("logger_class")
configure_class(logger_class, **options)
else:
configure_class(**options)
def memory_get(size=None):
if not C.LOG_OPT_OUTPUT_MEMORY in handlers:
raise ValueError('memory output is not used')
raise ValueError("memory output is not used")
return configure_cls[backend].memory_get(size)
def getLogger(name=C.LOG_BASE_LOGGER) -> Logger:
try:
logger_class = configure_cls[backend].LOGGER_CLASS
except KeyError:
raise ValueError("This method should not be called with backend [{}]".format(backend))
raise ValueError(
"This method should not be called with backend [{}]".format(backend)
)
return _loggers.setdefault(name, logger_class(name))
_root_logger = getLogger()
def debug(msg, **kwargs):
_root_logger.debug(msg, **kwargs)
def info(msg, **kwargs):
_root_logger.info(msg, **kwargs)
def warning(msg, **kwargs):
_root_logger.warning(msg, **kwargs)
def error(msg, **kwargs):
_root_logger.error(msg, **kwargs)
def critical(msg, **kwargs):
_root_logger.critical(msg, **kwargs)

View file

@ -31,6 +31,7 @@ class TwistedLogger(log.Logger):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
from twisted.logger import Logger
self.twisted_log = Logger()
def out(self, message, level=None, **kwargs):
@ -59,7 +60,7 @@ class ConfigureBasic(log.ConfigureBase):
except AttributeError:
isatty = False
# FIXME: isatty should be tested on each handler, not globaly
if (force_colors or isatty):
if force_colors or isatty:
# we need colors
log.Logger.post_treat = lambda logger, level, message: self.ansi_colors(
level, message
@ -109,6 +110,7 @@ class ConfigureTwisted(ConfigureBasic):
def pre_treatment(self):
from twisted import logger
global logger
self.level_map = {
C.LOG_LVL_DEBUG: logger.LogLevel.debug,
@ -125,6 +127,7 @@ class ConfigureTwisted(ConfigureBasic):
def configure_output(self, output):
import sys
from twisted.python import logfile
self.log_publisher = logger.LogPublisher()
if output is None:
@ -137,13 +140,15 @@ class ConfigureTwisted(ConfigureBasic):
"You must pass options as backend_data with Twisted backend"
)
options = self.backend_data
log_file = logfile.LogFile.fromFullPath(options['logfile'])
log_file = logfile.LogFile.fromFullPath(options["logfile"])
self.log_publisher.addObserver(
logger.FileLogObserver(log_file, self.text_formatter))
logger.FileLogObserver(log_file, self.text_formatter)
)
# we also want output to stdout if we are in debug or nodaemon mode
if options.get("nodaemon", False) or options.get("debug", False):
self.log_publisher.addObserver(
logger.FileLogObserver(sys.stdout, self.text_formatter))
logger.FileLogObserver(sys.stdout, self.text_formatter)
)
if C.LOG_OPT_OUTPUT_FILE in log.handlers:
@ -152,7 +157,8 @@ class ConfigureTwisted(ConfigureBasic):
sys.stdout if path == "-" else logfile.LogFile.fromFullPath(path)
)
self.log_publisher.addObserver(
logger.FileLogObserver(log_file, self.text_formatter))
logger.FileLogObserver(log_file, self.text_formatter)
)
if C.LOG_OPT_OUTPUT_MEMORY in log.handlers:
raise NotImplementedError(
@ -172,21 +178,21 @@ class ConfigureTwisted(ConfigureBasic):
"""Install twistedObserver which manage non SàT logs"""
# from twisted import logger
import sys
filtering_obs = logger.FilteringLogObserver(
observer=self.log_publisher,
predicates=[
logger.LogLevelFilterPredicate(self.level),
]
],
)
logger.globalLogBeginner.beginLoggingTo([filtering_obs])
def text_formatter(self, event):
if event.get('sat_logged', False):
timestamp = ''.join([logger.formatTime(event.get("log_time", None)), " "])
if event.get("sat_logged", False):
timestamp = "".join([logger.formatTime(event.get("log_time", None)), " "])
return f"{timestamp}{event.get('log_format', '')}\n"
else:
eventText = logger.eventAsText(
event, includeSystem=True)
eventText = logger.eventAsText(event, includeSystem=True)
if not eventText:
return None
return eventText.replace("\n", "\n\t") + "\n"
@ -241,6 +247,7 @@ class ConfigureStandard(ConfigureBasic):
class SatFormatter(logging.Formatter):
"""Formatter which manage SàT specificities"""
_format = fmt
_with_profile = "%(profile)s" in fmt
@ -310,11 +317,9 @@ class ConfigureStandard(ConfigureBasic):
super(SatMemoryHandler, self).emit(self.format(record))
hdlr = SatMemoryHandler(options)
log.handlers[
handler
] = (
hdlr
) # we keep a reference to the handler to read the buffer later
log.handlers[handler] = (
hdlr # we keep a reference to the handler to read the buffer later
)
self._add_handler(root_logger, hdlr, can_colors=False)
elif handler == C.LOG_OPT_OUTPUT_FILE:
import os.path

View file

@ -29,6 +29,7 @@ from wokkel.data_form import Option
from libervia import backend
from libervia.backend.core.i18n import _, D_, language_switch
from libervia.backend.core import patches
patches.apply()
from twisted.application import service
from twisted.internet import defer
@ -57,6 +58,7 @@ import libervia.backend.plugins
log = getLogger(__name__)
class LiberviaBackend(service.Service):
def _init(self):
@ -67,7 +69,7 @@ class LiberviaBackend(service.Service):
# dynamic menus. key: callback_id, value: menu data (dictionnary)
self._menus = {}
self._menus_paths = {} # path to id. key: (menu_type, lower case tuple of path),
# value: menu id
# value: menu id
# like initialised, but launched before init script is done, mainly useful for CLI
# frontend, so it can be used in init script, while other frontends are waiting.
@ -75,7 +77,7 @@ class LiberviaBackend(service.Service):
self.initialised = defer.Deferred()
self.profiles = {}
self.plugins = {}
# map for short name to whole namespace,
# map for short name to whole namespace,
# extended by plugins with register_namespace
self.ns_map = {
"x-data": xmpp.NS_X_DATA,
@ -85,13 +87,10 @@ class LiberviaBackend(service.Service):
self.memory = memory.Memory(self)
# trigger are used to change Libervia behaviour
self.trigger = (
trigger.TriggerManager()
)
self.trigger = trigger.TriggerManager()
bridge_name = (
os.getenv("LIBERVIA_BRIDGE_NAME")
or self.memory.config_get("", "bridge", "dbus")
bridge_name = os.getenv("LIBERVIA_BRIDGE_NAME") or self.memory.config_get(
"", "bridge", "dbus"
)
bridge_module = dynamic_import.bridge(bridge_name)
@ -120,7 +119,6 @@ class LiberviaBackend(service.Service):
else:
self.local_shared_path = None
defer.ensureDeferred(self._post_init())
@property
@ -174,40 +172,58 @@ class LiberviaBackend(service.Service):
self.bridge.register_method("entity_data_get", self.memory._get_entity_data)
self.bridge.register_method("entities_data_get", self.memory._get_entities_data)
self.bridge.register_method("profile_create", self.memory.create_profile)
self.bridge.register_method("profile_delete_async", self.memory.profile_delete_async)
self.bridge.register_method(
"profile_delete_async", self.memory.profile_delete_async
)
self.bridge.register_method("profile_start_session", self.memory.start_session)
self.bridge.register_method(
"profile_is_session_started", self.memory._is_session_started
)
self.bridge.register_method("profile_set_default", self.memory.profile_set_default)
self.bridge.register_method(
"profile_set_default", self.memory.profile_set_default
)
self.bridge.register_method("connect", self._connect)
self.bridge.register_method("disconnect", self.disconnect)
self.bridge.register_method("contact_get", self._contact_get)
self.bridge.register_method("contacts_get", self.contacts_get)
self.bridge.register_method("contacts_get_from_group", self.contacts_get_from_group)
self.bridge.register_method(
"contacts_get_from_group", self.contacts_get_from_group
)
self.bridge.register_method("main_resource_get", self.memory._get_main_resource)
self.bridge.register_method(
"presence_statuses_get", self.memory._get_presence_statuses
)
self.bridge.register_method("sub_waiting_get", self.memory.sub_waiting_get)
self.bridge.register_method("message_send", self._message_send)
self.bridge.register_method("message_encryption_start",
self._message_encryption_start)
self.bridge.register_method("message_encryption_stop",
self._message_encryption_stop)
self.bridge.register_method("message_encryption_get",
self._message_encryption_get)
self.bridge.register_method("encryption_namespace_get",
self._encryption_namespace_get)
self.bridge.register_method("encryption_plugins_get", self._encryption_plugins_get)
self.bridge.register_method("encryption_trust_ui_get", self._encryption_trust_ui_get)
self.bridge.register_method(
"message_encryption_start", self._message_encryption_start
)
self.bridge.register_method(
"message_encryption_stop", self._message_encryption_stop
)
self.bridge.register_method(
"message_encryption_get", self._message_encryption_get
)
self.bridge.register_method(
"encryption_namespace_get", self._encryption_namespace_get
)
self.bridge.register_method(
"encryption_plugins_get", self._encryption_plugins_get
)
self.bridge.register_method(
"encryption_trust_ui_get", self._encryption_trust_ui_get
)
self.bridge.register_method("config_get", self._get_config)
self.bridge.register_method("param_set", self.param_set)
self.bridge.register_method("param_get_a", self.memory.get_string_param_a)
self.bridge.register_method("private_data_get", self.memory._private_data_get)
self.bridge.register_method("private_data_set", self.memory._private_data_set)
self.bridge.register_method("private_data_delete", self.memory._private_data_delete)
self.bridge.register_method("param_get_a_async", self.memory.async_get_string_param_a)
self.bridge.register_method(
"private_data_delete", self.memory._private_data_delete
)
self.bridge.register_method(
"param_get_a_async", self.memory.async_get_string_param_a
)
self.bridge.register_method(
"params_values_from_category_get_async",
self.memory._get_params_values_from_category,
@ -216,7 +232,9 @@ class LiberviaBackend(service.Service):
self.bridge.register_method(
"params_categories_get", self.memory.params_categories_get
)
self.bridge.register_method("params_register_app", self.memory.params_register_app)
self.bridge.register_method(
"params_register_app", self.memory.params_register_app
)
self.bridge.register_method("history_get", self.memory._history_get)
self.bridge.register_method("presence_set", self._set_presence)
self.bridge.register_method("subscription", self.subscription)
@ -242,13 +260,18 @@ class LiberviaBackend(service.Service):
self.bridge.register_method("namespaces_get", self.get_namespaces)
self.bridge.register_method("image_check", self._image_check)
self.bridge.register_method("image_resize", self._image_resize)
self.bridge.register_method("image_generate_preview", self._image_generate_preview)
self.bridge.register_method(
"image_generate_preview", self._image_generate_preview
)
self.bridge.register_method("image_convert", self._image_convert)
self.bridge.register_method("notification_add", self.memory._add_notification)
self.bridge.register_method("notifications_get", self.memory._get_notifications)
self.bridge.register_method("notification_delete", self.memory._delete_notification)
self.bridge.register_method("notifications_expired_clean", self.memory._notifications_expired_clean)
self.bridge.register_method(
"notification_delete", self.memory._delete_notification
)
self.bridge.register_method(
"notifications_expired_clean", self.memory._notifications_expired_clean
)
await self.memory.initialise()
self.common_cache = cache.Cache(self, None)
@ -277,10 +300,7 @@ class LiberviaBackend(service.Service):
else:
log.info(f"Running init script {init_script!r}.")
try:
await async_process.run(
str(init_script),
verbose=True
)
await async_process.run(str(init_script), verbose=True)
except RuntimeError as e:
log.error(f"Init script failed: {e}")
self.stopService()
@ -292,15 +312,18 @@ class LiberviaBackend(service.Service):
# profile autoconnection must be done after self.initialised is called because
# start_session waits for it.
autoconnect_dict = await self.memory.storage.get_ind_param_values(
category='Connection', name='autoconnect_backend',
category="Connection",
name="autoconnect_backend",
)
profiles_autoconnect = [p for p, v in autoconnect_dict.items() if C.bool(v)]
if not self.trigger.point("profilesAutoconnect", profiles_autoconnect):
return
if profiles_autoconnect:
log.info(D_(
"Following profiles will be connected automatically: {profiles}"
).format(profiles= ', '.join(profiles_autoconnect)))
log.info(
D_(
"Following profiles will be connected automatically: {profiles}"
).format(profiles=", ".join(profiles_autoconnect))
)
connect_d_list = []
for profile in profiles_autoconnect:
connect_d_list.append(defer.ensureDeferred(self.connect(profile)))
@ -312,8 +335,8 @@ class LiberviaBackend(service.Service):
profile = profiles_autoconnect[0]
log.warning(
_("Can't autoconnect profile {profile}: {reason}").format(
profile = profile,
reason = result)
profile=profile, reason=result
)
)
def _add_base_menus(self):
@ -342,7 +365,8 @@ class LiberviaBackend(service.Service):
init_path = plug_path / f"__init__.{C.PLUGIN_EXT}"
if not init_path.exists():
log.warning(
f"{plug_path} doesn't appear to be a package, can't load it")
f"{plug_path} doesn't appear to be a package, can't load it"
)
continue
plug_name = plug_path.name
elif plug_path.is_file():
@ -350,12 +374,12 @@ class LiberviaBackend(service.Service):
continue
plug_name = plug_path.stem
else:
log.warning(
f"{plug_path} is not a file or a dir, ignoring it")
log.warning(f"{plug_path} is not a file or a dir, ignoring it")
continue
if not plug_name.isidentifier():
log.warning(
f"{plug_name!r} is not a valid name for a plugin, ignoring it")
f"{plug_name!r} is not a valid name for a plugin, ignoring it"
)
continue
plugin_path = f"libervia.backend.plugins.{plug_name}"
try:
@ -364,9 +388,7 @@ class LiberviaBackend(service.Service):
self._unimport_plugin(plugin_path)
log.warning(
"Can't import plugin [{path}] because of an unavailale third party "
"module:\n{msg}".format(
path=plugin_path, msg=e
)
"module:\n{msg}".format(path=plugin_path, msg=e)
)
continue
except exceptions.CancelError as e:
@ -450,9 +472,7 @@ class LiberviaBackend(service.Service):
else:
if not import_name in plugins_to_import:
if optional:
log.warning(
_("Recommended plugin not found: {}").format(import_name)
)
log.warning(_("Recommended plugin not found: {}").format(import_name))
return
msg = "Dependency not found: {}".format(import_name)
log.error(msg)
@ -521,7 +541,8 @@ class LiberviaBackend(service.Service):
return defer.ensureDeferred(self.connect(profile, password, options))
async def connect(
self, profile, password="", options=None, max_retries=C.XMPP_MAX_RETRIES):
self, profile, password="", options=None, max_retries=C.XMPP_MAX_RETRIES
):
"""Connect a profile (i.e. connect client.component to XMPP server)
Retrieve the individual parameters, authenticate the profile
@ -761,16 +782,14 @@ class LiberviaBackend(service.Service):
try:
return self.ns_map[short_name]
except KeyError:
raise exceptions.NotFound("namespace {short_name} is not registered"
.format(short_name=short_name))
raise exceptions.NotFound(
"namespace {short_name} is not registered".format(short_name=short_name)
)
def get_session_infos(self, profile_key):
"""compile interesting data on current profile session"""
client = self.get_client(profile_key)
data = {
"jid": client.jid.full(),
"started": str(int(client.started))
}
data = {"jid": client.jid.full(), "started": str(int(client.started))}
return defer.succeed(data)
def _get_devices_infos(self, bare_jid, profile_key):
@ -808,11 +827,11 @@ class LiberviaBackend(service.Service):
"resource": resource,
}
try:
presence = cache_data['presence']
presence = cache_data["presence"]
except KeyError:
pass
else:
res_data['presence'] = {
res_data["presence"] = {
"show": presence.show,
"priority": presence.priority,
"statuses": presence.statuses,
@ -821,12 +840,14 @@ class LiberviaBackend(service.Service):
disco = await self.get_disco_infos(client, res_jid)
for (category, type_), name in disco.identities.items():
identities = res_data.setdefault('identities', [])
identities.append({
"name": name,
"category": category,
"type": type_,
})
identities = res_data.setdefault("identities", [])
identities.append(
{
"name": name,
"category": category,
"type": type_,
}
)
ret_data.append(res_data)
@ -857,7 +878,7 @@ class LiberviaBackend(service.Service):
"""
report = image.check(self, path, max_size=(300, 300))
if not report['too_large']:
if not report["too_large"]:
# in the unlikely case that image is already smaller than a preview
preview_path = path
else:
@ -867,17 +888,14 @@ class LiberviaBackend(service.Service):
filename = f"{uid}{path.suffix.lower()}"
metadata = client.cache.get_metadata(uid=uid)
if metadata is not None:
preview_path = metadata['path']
preview_path = metadata["path"]
else:
with client.cache.cache_data(
source='HOST_PREVIEW',
uid=uid,
filename=filename) as cache_f:
source="HOST_PREVIEW", uid=uid, filename=filename
) as cache_f:
preview_path = await image.resize(
path,
new_size=report['recommended_size'],
dest=cache_f
path, new_size=report["recommended_size"], dest=cache_f
)
return preview_path
@ -922,23 +940,19 @@ class LiberviaBackend(service.Service):
metadata = cache.get_metadata(uid=uid)
if metadata is not None:
# there is already a conversion for this image in cache
return metadata['path']
return metadata["path"]
else:
with cache.cache_data(
source='HOST_IMAGE_CONVERT',
uid=uid,
filename=filename) as cache_f:
source="HOST_IMAGE_CONVERT", uid=uid, filename=filename
) as cache_f:
converted_path = await image.convert(
source,
dest=cache_f,
extra=extra
source, dest=cache_f, extra=extra
)
return converted_path
else:
return await image.convert(source, dest, extra)
# local dirs
def get_local_path(
@ -998,18 +1012,19 @@ class LiberviaBackend(service.Service):
def register_encryption_plugin(self, *args, **kwargs):
return encryption.EncryptionHandler.register_plugin(*args, **kwargs)
def _message_encryption_start(self, to_jid_s, namespace, replace=False,
profile_key=C.PROF_KEY_NONE):
def _message_encryption_start(
self, to_jid_s, namespace, replace=False, profile_key=C.PROF_KEY_NONE
):
client = self.get_client(profile_key)
to_jid = jid.JID(to_jid_s)
return defer.ensureDeferred(
client.encryption.start(to_jid, namespace or None, replace))
client.encryption.start(to_jid, namespace or None, replace)
)
def _message_encryption_stop(self, to_jid_s, profile_key=C.PROF_KEY_NONE):
client = self.get_client(profile_key)
to_jid = jid.JID(to_jid_s)
return defer.ensureDeferred(
client.encryption.stop(to_jid))
return defer.ensureDeferred(client.encryption.stop(to_jid))
def _message_encryption_get(self, to_jid_s, profile_key=C.PROF_KEY_NONE):
client = self.get_client(profile_key)
@ -1024,42 +1039,48 @@ class LiberviaBackend(service.Service):
plugins = encryption.EncryptionHandler.getPlugins()
ret = []
for p in plugins:
ret.append({
"name": p.name,
"namespace": p.namespace,
"priority": p.priority,
"directed": p.directed,
})
ret.append(
{
"name": p.name,
"namespace": p.namespace,
"priority": p.priority,
"directed": p.directed,
}
)
return data_format.serialise(ret)
def _encryption_trust_ui_get(self, to_jid_s, namespace, profile_key):
client = self.get_client(profile_key)
to_jid = jid.JID(to_jid_s)
d = defer.ensureDeferred(
client.encryption.get_trust_ui(to_jid, namespace=namespace or None))
client.encryption.get_trust_ui(to_jid, namespace=namespace or None)
)
d.addCallback(lambda xmlui: xmlui.toXml())
return d
## XMPP methods ##
def _message_send(
self, to_jid_s, message, subject=None, mess_type="auto", extra_s="",
profile_key=C.PROF_KEY_NONE):
self,
to_jid_s,
message,
subject=None,
mess_type="auto",
extra_s="",
profile_key=C.PROF_KEY_NONE,
):
client = self.get_client(profile_key)
to_jid = jid.JID(to_jid_s)
return client.sendMessage(
to_jid,
message,
subject,
mess_type,
data_format.deserialise(extra_s)
to_jid, message, subject, mess_type, data_format.deserialise(extra_s)
)
def _set_presence(self, to="", show="", statuses=None, profile_key=C.PROF_KEY_NONE):
return self.presence_set(jid.JID(to) if to else None, show, statuses, profile_key)
def presence_set(self, to_jid=None, show="", statuses=None,
profile_key=C.PROF_KEY_NONE):
def presence_set(
self, to_jid=None, show="", statuses=None, profile_key=C.PROF_KEY_NONE
):
"""Send our presence information"""
if statuses is None:
statuses = {}
@ -1116,7 +1137,7 @@ class LiberviaBackend(service.Service):
def contact_update(self, client, to_jid, name, groups):
"""update a contact in roster list"""
roster_item = RosterItem(to_jid)
roster_item.name = name or u''
roster_item.name = name or ""
roster_item.groups = set(groups)
if not self.trigger.point("roster_update", client, roster_item):
return
@ -1167,28 +1188,46 @@ class LiberviaBackend(service.Service):
def find_features_set(self, *args, **kwargs):
return self.memory.disco.find_features_set(*args, **kwargs)
def _find_by_features(self, namespaces, identities, bare_jids, service, roster, own_jid,
local_device, profile_key):
def _find_by_features(
self,
namespaces,
identities,
bare_jids,
service,
roster,
own_jid,
local_device,
profile_key,
):
client = self.get_client(profile_key)
identities = [tuple(i) for i in identities] if identities else None
return defer.ensureDeferred(self.find_by_features(
client, namespaces, identities, bare_jids, service, roster, own_jid,
local_device))
return defer.ensureDeferred(
self.find_by_features(
client,
namespaces,
identities,
bare_jids,
service,
roster,
own_jid,
local_device,
)
)
async def find_by_features(
self,
client: SatXMPPEntity,
namespaces: List[str],
identities: Optional[List[Tuple[str, str]]]=None,
bare_jids: bool=False,
service: bool=True,
roster: bool=True,
own_jid: bool=True,
local_device: bool=False
identities: Optional[List[Tuple[str, str]]] = None,
bare_jids: bool = False,
service: bool = True,
roster: bool = True,
own_jid: bool = True,
local_device: bool = False,
) -> Tuple[
Dict[jid.JID, Tuple[str, str, str]],
Dict[jid.JID, Tuple[str, str, str]],
Dict[jid.JID, Tuple[str, str, str]]
Dict[jid.JID, Tuple[str, str, str]],
]:
"""Retrieve all services or contacts managing a set a features
@ -1224,19 +1263,25 @@ class LiberviaBackend(service.Service):
if service:
services_jids = await self.find_features_set(client, namespaces)
services_jids = list(services_jids) # we need a list to map results below
services_infos = await defer.DeferredList(
[self.get_disco_infos(client, service_jid) for service_jid in services_jids]
services_infos = await defer.DeferredList(
[
self.get_disco_infos(client, service_jid)
for service_jid in services_jids
]
)
for idx, (success, infos) in enumerate(services_infos):
service_jid = services_jids[idx]
if not success:
log.warning(
_("Can't find features for service {service_jid}, ignoring")
.format(service_jid=service_jid.full()))
_(
"Can't find features for service {service_jid}, ignoring"
).format(service_jid=service_jid.full())
)
continue
if (identities is not None
and not set(infos.identities.keys()).issuperset(identities)):
if identities is not None and not set(infos.identities.keys()).issuperset(
identities
):
continue
found_identities = [
(cat, type_, name or "")
@ -1291,8 +1336,10 @@ class LiberviaBackend(service.Service):
full_jid = full_jids[idx]
if not success:
log.warning(
_("Can't retrieve {full_jid} infos, ignoring")
.format(full_jid=full_jid.full()))
_("Can't retrieve {full_jid} infos, ignoring").format(
full_jid=full_jid.full()
)
)
continue
if infos.features.issuperset(namespaces):
if identities is not None and not set(
@ -1476,21 +1523,16 @@ class LiberviaBackend(service.Service):
return callback_id
def remove_callback(self, callback_id):
""" Remove a previously registered callback
@param callback_id: id returned by [register_callback] """
"""Remove a previously registered callback
@param callback_id: id returned by [register_callback]"""
log.debug("Removing callback [%s]" % callback_id)
del self._cb_map[callback_id]
def _action_launch(
self,
callback_id: str,
data_s: str,
profile_key: str
self, callback_id: str, data_s: str, profile_key: str
) -> defer.Deferred:
d = self.launch_callback(
callback_id,
data_format.deserialise(data_s),
profile_key
callback_id, data_format.deserialise(data_s), profile_key
)
d.addCallback(data_format.serialise)
return d
@ -1499,7 +1541,7 @@ class LiberviaBackend(service.Service):
self,
callback_id: str,
data: Optional[dict] = None,
profile_key: str = C.PROF_KEY_NONE
profile_key: str = C.PROF_KEY_NONE,
) -> defer.Deferred:
"""Launch a specific callback
@ -1568,8 +1610,14 @@ class LiberviaBackend(service.Service):
"""
return tuple((p.lower().strip() for p in path))
def import_menu(self, path, callback, security_limit=C.NO_SECURITY_LIMIT,
help_string="", type_=C.MENU_GLOBAL):
def import_menu(
self,
path,
callback,
security_limit=C.NO_SECURITY_LIMIT,
help_string="",
type_=C.MENU_GLOBAL,
):
r"""register a new menu for frontends
@param path(iterable[unicode]): path to go to the menu
@ -1677,13 +1725,20 @@ class LiberviaBackend(service.Service):
return ret
def _launch_menu(self, menu_type, path, data=None, security_limit=C.NO_SECURITY_LIMIT,
profile_key=C.PROF_KEY_NONE):
def _launch_menu(
self,
menu_type,
path,
data=None,
security_limit=C.NO_SECURITY_LIMIT,
profile_key=C.PROF_KEY_NONE,
):
client = self.get_client(profile_key)
return self.launch_menu(client, menu_type, path, data, security_limit)
def launch_menu(self, client, menu_type, path, data=None,
security_limit=C.NO_SECURITY_LIMIT):
def launch_menu(
self, client, menu_type, path, data=None, security_limit=C.NO_SECURITY_LIMIT
):
"""launch action a menu action
@param menu_type(unicode): type of menu to launch

Some files were not shown because too many files have changed in this diff Show more