primitivus, jp: dynamic bridge + fixed D-Bus bridge:
Primitivus and jp can now load the bridge specified in sat.conf, but they are only working with D-Bus so far (need to change all sync calls to async).
Exit code 3 is used for Bridge init error.
This commit is contained in:
parent
be8d681be7
commit
0a5fd6f3f4
5 changed files with 114 additions and 29 deletions
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
|
||||
class BridgeFrontend(object):
|
||||
def __init__(self):
|
||||
print "Bridge frontend initialization"
|
||||
|
||||
def register(self, functionName, handler):
|
||||
raise NotImplementedError
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@ import sys
|
|||
import locale
|
||||
import os.path
|
||||
import argparse
|
||||
from gi.repository import GLib
|
||||
from glob import iglob
|
||||
from importlib import import_module
|
||||
from sat_frontends.tools.jid import JID
|
||||
from sat_frontends.bridge.dbus_bridge import Bridge
|
||||
from sat.tools import config
|
||||
from sat.tools.common import dynamic_import
|
||||
from sat.core import exceptions
|
||||
import sat_frontends.jp
|
||||
from sat_frontends.jp.constants import Const as C
|
||||
|
|
@ -41,6 +41,66 @@ import xml.etree.ElementTree as ET # FIXME: used temporarily to manage XMLUI
|
|||
import shlex
|
||||
from collections import OrderedDict
|
||||
|
||||
## bridge handling
|
||||
# we get bridge name from conf and initialise the right class accordingly
|
||||
main_config = config.parseMainConf()
|
||||
bridge_name = config.getConfig(main_config, '', 'bridge', 'dbus')
|
||||
|
||||
|
||||
# TODO: move loops handling in a separated module
|
||||
if 'dbus' in bridge_name:
|
||||
from gi.repository import GLib
|
||||
|
||||
|
||||
class JPLoop(object):
|
||||
|
||||
def __init__(self):
|
||||
self.loop = GLib.MainLoop()
|
||||
|
||||
def run(self):
|
||||
self.loop.run()
|
||||
|
||||
def quit(self):
|
||||
self.loop.quit()
|
||||
|
||||
def call_later(self, delay, callback, *args):
|
||||
"""call a callback repeatedly
|
||||
|
||||
@param delay(int): delay between calls in ms
|
||||
@param callback(callable): method to call
|
||||
if the callback return True, the call will continue
|
||||
else the calls will stop
|
||||
@param *args: args of the callbac
|
||||
"""
|
||||
GLib.timeout_add(delay, callback, *args)
|
||||
|
||||
else:
|
||||
print u"can't start jp: only D-Bus bridge is currently handled"
|
||||
sys.exit(C.EXIT_ERROR)
|
||||
# FIXME: twisted loop can be used when jp can handle fully async bridges
|
||||
# from twisted.internet import reactor
|
||||
|
||||
# class JPLoop(object):
|
||||
|
||||
# def run(self):
|
||||
# reactor.run()
|
||||
|
||||
# def quit(self):
|
||||
# reactor.stop()
|
||||
|
||||
# def _timeout_cb(self, args, callback, delay):
|
||||
# ret = callback(*args)
|
||||
# if ret:
|
||||
# reactor.callLater(delay, self._timeout_cb, args, callback, delay)
|
||||
|
||||
# def call_later(self, delay, callback, *args):
|
||||
# delay = float(delay) / 1000
|
||||
# reactor.callLater(delay, self._timeout_cb, args, callback, delay)
|
||||
|
||||
if bridge_name == "embedded":
|
||||
from sat.core import sat_main
|
||||
sat = sat_main.SAT()
|
||||
|
||||
if sys.version_info < (2, 7, 3):
|
||||
# XXX: shlex.split only handle unicode since python 2.7.3
|
||||
# this is a workaround for older versions
|
||||
|
|
@ -52,8 +112,8 @@ if sys.version_info < (2, 7, 3):
|
|||
try:
|
||||
import progressbar
|
||||
except ImportError:
|
||||
log.info (_('ProgressBar not available, please download it at http://pypi.python.org/pypi/progressbar'))
|
||||
log.info (_('Progress bar deactivated\n--\n'))
|
||||
log.info (_(u'ProgressBar not available, please download it at http://pypi.python.org/pypi/progressbar'))
|
||||
log.info (_(u'Progress bar deactivated\n--\n'))
|
||||
progressbar=None
|
||||
|
||||
#consts
|
||||
|
|
@ -95,18 +155,19 @@ class Jp(object):
|
|||
@attribute progress_failure(callable): method to call when progress failed
|
||||
by default display a message
|
||||
"""
|
||||
try:
|
||||
self.bridge = Bridge()
|
||||
except exceptions.BridgeExceptionNoService:
|
||||
print(_(u"Can't connect to SàT backend, are you sure it's launched ?"))
|
||||
sys.exit(1)
|
||||
except exceptions.BridgeInitError:
|
||||
print(_(u"Can't init bridge"))
|
||||
# FIXME: need_loop should be removed, everything must be async in bridge so
|
||||
# loop will always be needed
|
||||
bridge_module = dynamic_import.bridge(bridge_name, 'sat_frontends.bridge')
|
||||
if bridge_module is None:
|
||||
log.error(u"Can't import {} bridge".format(bridge_name))
|
||||
sys.exit(1)
|
||||
|
||||
self.bridge = bridge_module.Bridge()
|
||||
self.bridge.bridgeConnect(callback=self._bridgeCb, errback=self._bridgeEb)
|
||||
|
||||
def _bridgeCb(self):
|
||||
self.parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=DESCRIPTION)
|
||||
|
||||
self._make_parents()
|
||||
self.add_parser_options()
|
||||
self.subparsers = self.parser.add_subparsers(title=_('Available commands'), dest='subparser_name')
|
||||
|
|
@ -122,6 +183,15 @@ class Jp(object):
|
|||
for type_ in C.OUTPUT_TYPES:
|
||||
self._outputs[type_] = OrderedDict()
|
||||
|
||||
def _bridgeEb(self, failure):
|
||||
if isinstance(failure, exceptions.BridgeExceptionNoService):
|
||||
print(_(u"Can't connect to SàT backend, are you sure it's launched ?"))
|
||||
elif isinstance(failure, exceptions.BridgeInitError):
|
||||
print(_(u"Can't init bridge"))
|
||||
else:
|
||||
print(_(u"Error while initialising bridge: {}".format(failure)))
|
||||
sys.exit(C.EXIT_BRIDGE_ERROR)
|
||||
|
||||
@property
|
||||
def version(self):
|
||||
return self.bridge.getVersion()
|
||||
|
|
@ -287,7 +357,7 @@ class Jp(object):
|
|||
log.info(_("User interruption: good bye"))
|
||||
|
||||
def _start_loop(self):
|
||||
self.loop = GLib.MainLoop()
|
||||
self.loop = JPLoop()
|
||||
self.loop.run()
|
||||
|
||||
def stop_loop(self):
|
||||
|
|
@ -304,7 +374,7 @@ class Jp(object):
|
|||
assert self._need_loop
|
||||
# XXX: python-dbus will show a traceback if we exit in a signal handler
|
||||
# so we use this little timeout trick to avoid it
|
||||
GLib.timeout_add(0, self.quit, errcode)
|
||||
self.loop.call_later(0, self.quit, errcode)
|
||||
|
||||
def quit(self, errcode=0):
|
||||
# first the onQuitCallbacks
|
||||
|
|
@ -437,7 +507,8 @@ class CommandBase(object):
|
|||
|
||||
def __init__(self, host, name, use_profile=True, use_output=False,
|
||||
need_connect=None, help=None, **kwargs):
|
||||
""" Initialise CommandBase
|
||||
"""Initialise CommandBase
|
||||
|
||||
@param host: Jp instance
|
||||
@param name(unicode): name of the new command
|
||||
@param use_profile(bool): if True, add profile selection/connection commands
|
||||
|
|
@ -453,7 +524,6 @@ class CommandBase(object):
|
|||
progress* signals will be handled
|
||||
- use_verbose(bool): if True, add verbosity option
|
||||
@attribute need_loop(bool): to set by commands when loop is needed
|
||||
|
||||
"""
|
||||
self.need_loop = False # to be set by commands when loop is needed
|
||||
try: # If we have subcommands, host is a CommandBase and we need to use host.host
|
||||
|
|
@ -536,7 +606,7 @@ class CommandBase(object):
|
|||
else:
|
||||
if self.host.watch_progress and uid == self.progress_id:
|
||||
self.onProgressStarted(metadata)
|
||||
GLib.timeout_add(PROGRESS_DELAY, self.progressUpdate)
|
||||
self.loop.call_later(PROGRESS_DELAY, self.progressUpdate)
|
||||
|
||||
def progressFinishedHandler(self, uid, metadata, profile):
|
||||
if profile != self.profile:
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ class Const(constants.Const):
|
|||
EXIT_OK = 0
|
||||
EXIT_ERROR = 1 # generic error, when nothing else match
|
||||
EXIT_BAD_ARG = 2 # arguments given by user are bad
|
||||
EXIT_BRIDGE_ERROR = 3 # can't connect to bridge
|
||||
EXIT_NOT_FOUND = 16 # an item required by a command was not found
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ from sat.tools import config as sat_config
|
|||
import urwid
|
||||
from urwid.util import is_wide_char
|
||||
from urwid_satext import sat_widgets
|
||||
from sat_frontends.bridge.dbus_bridge import Bridge
|
||||
from sat_frontends.quick_frontend.quick_app import QuickApp
|
||||
from sat_frontends.quick_frontend import quick_utils
|
||||
from sat_frontends.quick_frontend import quick_chat
|
||||
|
|
@ -41,9 +40,17 @@ from sat_frontends.primitivus.notify import Notify
|
|||
from sat_frontends.primitivus.keys import action_key_map as a_key
|
||||
from sat_frontends.primitivus import config
|
||||
from sat_frontends.tools.misc import InputHistory
|
||||
from sat.tools.common import dynamic_import
|
||||
from sat_frontends.tools import jid
|
||||
import signal
|
||||
import sys
|
||||
## bridge handling
|
||||
# we get bridge name from conf and initialise the right class accordingly
|
||||
main_config = sat_config.parseMainConf()
|
||||
bridge_name = sat_config.getConfig(main_config, '', 'bridge', 'dbus')
|
||||
if 'dbus' not in bridge_name:
|
||||
print(u"only D-Bus bridge is currently supported")
|
||||
sys.exit(3)
|
||||
|
||||
|
||||
class EditBar(sat_widgets.ModalEdit):
|
||||
|
|
@ -276,11 +283,18 @@ class PrimitivusApp(QuickApp, InputHistory):
|
|||
AVATAR_HANDLER = False
|
||||
|
||||
def __init__(self):
|
||||
QuickApp.__init__(self, create_bridge=Bridge, xmlui=xmlui, check_options=quick_utils.check_options)
|
||||
|
||||
bridge_module = dynamic_import.bridge(bridge_name, 'sat_frontends.bridge')
|
||||
if bridge_module is None:
|
||||
log.error(u"Can't import {} bridge".format(bridge_name))
|
||||
sys.exit(3)
|
||||
else:
|
||||
log.debug(u"Loading {} bridge".format(bridge_name))
|
||||
QuickApp.__init__(self, bridge_factory=bridge_module.Bridge, xmlui=xmlui, check_options=quick_utils.check_options, connect_bridge=False)
|
||||
## main loop setup ##
|
||||
self.main_widget = ProfileManager(self)
|
||||
self.loop = urwid.MainLoop(self.main_widget, C.PALETTE, event_loop=urwid.GLibEventLoop(), input_filter=self.inputFilter, unhandled_input=self.keyHandler)
|
||||
event_loop = urwid.GLibEventLoop if 'dbus' in bridge_name else urwid.TwistedEventLoop
|
||||
self.loop = urwid.MainLoop(urwid.SolidFill(), C.PALETTE, event_loop=event_loop(), input_filter=self.inputFilter, unhandled_input=self.keyHandler)
|
||||
|
||||
def onBridgeConnected(self):
|
||||
|
||||
##misc setup##
|
||||
self._visible_widgets = set()
|
||||
|
|
@ -302,6 +316,9 @@ class PrimitivusApp(QuickApp, InputHistory):
|
|||
sys.stdout.write("\033[?2004h")
|
||||
self._bracketed_mode_set = True
|
||||
|
||||
self.loop.widget = self.main_widget = ProfileManager(self)
|
||||
self.postInit()
|
||||
|
||||
@property
|
||||
def visible_widgets(self):
|
||||
return self._visible_widgets
|
||||
|
|
@ -343,8 +360,7 @@ class PrimitivusApp(QuickApp, InputHistory):
|
|||
pass
|
||||
|
||||
def start(self):
|
||||
self.i = 0
|
||||
self.loop.set_alarm_in(0,lambda a,b: self.postInit())
|
||||
self.connectBridge()
|
||||
self.loop.run()
|
||||
|
||||
def postInit(self):
|
||||
|
|
@ -813,5 +829,5 @@ class PrimitivusApp(QuickApp, InputHistory):
|
|||
else:
|
||||
log.warning(u"No ContactList widget found for profile {}".format(profile))
|
||||
|
||||
sat = PrimitivusApp()
|
||||
sat.start()
|
||||
primitivus = PrimitivusApp()
|
||||
primitivus.start()
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ from sat.core import exceptions
|
|||
|
||||
class _Bridge(object):
|
||||
def __init__(self):
|
||||
log.info(u"Init embedded bridge...")
|
||||
log.debug(u"Init embedded bridge...")
|
||||
self._methods_cbs = {}
|
||||
self._signals_cbs = {
|
||||
"core": {},
|
||||
|
|
|
|||
Loading…
Reference in a new issue