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:
Goffi 2016-12-18 16:28:51 +01:00
commit 0a5fd6f3f4

View file

@ -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: