# HG changeset patch # User Goffi # Date 1480871808 -3600 # Node ID 0931b5a6213c9a2b203feeb02f29b0f529250da8 # Parent c02f96756d5c40811ba530bf833542bb451e079e core, quick_frontends: android compatibility hacks: a couple of hacks have been used so backend can be launched on android using kivy - config file (sat.conf) is been read on a specific dir, using a detection of Cagou domains in constants.py - fixed crash when using sys.stdout.isatty in log_config.py - Q&D fix for logging encoding issue on android - when android is detected, the path/pattern to load plugins is modified - SRV is not working at the moment on android. If the platform is detected, the host is used directly with default port. A hosts_dir configuration can be used in [android] section to map a specific ip to a host - getRepositoryData in tools/utils return constant string on android. Proper repository data need to be copied during package building. - [quick app] more robust failure handling on asyncConnect error - [quick chat] default to utf-8 when getlocale doesn't return the actual locale. diff -r c02f96756d5c -r 0931b5a6213c frontends/src/quick_frontend/quick_app.py --- a/frontends/src/quick_frontend/quick_app.py Sun Dec 04 18:16:37 2016 +0100 +++ b/frontends/src/quick_frontend/quick_app.py Sun Dec 04 18:16:48 2016 +0100 @@ -402,10 +402,22 @@ if not errback: def errback(failure): log.error(_(u"Can't connect profile [%s]") % failure) - if failure.module.startswith('twisted.words.protocols.jabber') and failure.condition == "not-authorized": + try: + module = failure.module + except AttributeError: + module = '' + try: + message = failure.message + except AttributeError: + message = 'error' + try: + fullname = failure.fullname + except AttributeError: + fullname = 'error' + if module.startswith('twisted.words.protocols.jabber') and failure.condition == "not-authorized": self.launchAction(C.CHANGE_XMPP_PASSWD_ID, {}, profile=profile) else: - self.showDialog(failure.message, failure.fullname, 'error') + self.showDialog(message, fullname, 'error') self.bridge.asyncConnect(profile, callback=callback, errback=errback) def plug_profiles(self, profiles): diff -r c02f96756d5c -r 0931b5a6213c frontends/src/quick_frontend/quick_chat.py --- a/frontends/src/quick_frontend/quick_chat.py Sun Dec 04 18:16:37 2016 +0100 +++ b/frontends/src/quick_frontend/quick_chat.py Sun Dec 04 18:16:48 2016 +0100 @@ -122,7 +122,7 @@ # if the message was sent before today, we print the full date timestamp = time.localtime(self.timestamp) time_format = u"%c" if timestamp < self.parent.day_change else u"%H:%M" - return time.strftime(time_format, timestamp).decode(getlocale()[1]) + return time.strftime(time_format, timestamp).decode(getlocale()[1] or 'utf-8') @property def avatar(self): @@ -470,7 +470,7 @@ self._onHistoryPrinted() def _historyGetEb(err): - log.error(_(u"Can't get history")) + log.error(_(u"Can't get history: {}").format(err)) self._onHistoryPrinted() self.host.bridge.historyGet(unicode(self.host.profiles[profile].whoami.bare), unicode(target), size, True, filters, profile, callback=_historyGetCb, errback=_historyGetEb) diff -r c02f96756d5c -r 0931b5a6213c src/core/constants.py --- a/src/core/constants.py Sun Dec 04 18:16:37 2016 +0100 +++ b/src/core/constants.py Sun Dec 04 18:16:48 2016 +0100 @@ -132,20 +132,32 @@ ## Configuration ## if BaseDirectory: # skipped when xdg module is not available (should not happen in backend) + if "org.goffi.cagou.cagou" in BaseDirectory.__file__: + # FIXME: hack to make config read from the right location on Android + # TODO: fix it in a more proper way + BaseDirectory = None + DEFAULT_CONFIG = { + 'local_dir': '/data/data/org.goffi.cagou.cagou/', + 'media_dir': '/data/data/org.goffi.cagou.cagou/files/media', + 'pid_dir': '%(local_dir)s', + 'log_dir': '%(local_dir)s', + } + CONFIG_FILES = ['/data/data/org.goffi.cagou.cagou/files/' + APP_NAME_FILE + '.conf'] + else: - ## Configuration ## - DEFAULT_CONFIG = { - 'media_dir': '/usr/share/' + APP_NAME_FILE + '/media', - 'local_dir': BaseDirectory.save_data_path(APP_NAME_FILE), - 'pid_dir': '%(local_dir)s', - 'log_dir': '%(local_dir)s', - } + ## Configuration ## + DEFAULT_CONFIG = { + 'media_dir': '/usr/share/' + APP_NAME_FILE + '/media', + 'local_dir': BaseDirectory.save_data_path(APP_NAME_FILE), + 'pid_dir': '%(local_dir)s', + 'log_dir': '%(local_dir)s', + } - # List of the configuration filenames sorted by ascending priority - CONFIG_FILES = [realpath(expanduser(path) + APP_NAME_FILE + '.conf') for path in - ['/etc/', '~/', '~/.', '', '.'] + - ['%s/' % path for path in list(BaseDirectory.load_config_paths(APP_NAME_FILE))] - ] + # List of the configuration filenames sorted by ascending priority + CONFIG_FILES = [realpath(expanduser(path) + APP_NAME_FILE + '.conf') for path in + ['/etc/', '~/', '~/.', '', '.'] + + ['%s/' % path for path in list(BaseDirectory.load_config_paths(APP_NAME_FILE))] + ] ## Plugins ## diff -r c02f96756d5c -r 0931b5a6213c src/core/log_config.py --- a/src/core/log_config.py Sun Dec 04 18:16:37 2016 +0100 +++ b/src/core/log_config.py Sun Dec 04 18:16:48 2016 +0100 @@ -47,7 +47,11 @@ super(ConfigureBasic, self).configureColors(colors, force_colors, levels_taints_dict) if colors: import sys - if force_colors or sys.stdout.isatty(): # FIXME: isatty should be tested on each handler, not globaly + try: + isatty = sys.stdout.isatty() + except AttributeError: + isatty = False + if force_colors or isatty: # FIXME: isatty should be tested on each handler, not globaly # we need colors log.Logger.post_treat = lambda logger, level, message: self.ansiColors(level, message) elif force_colors: @@ -262,6 +266,7 @@ def configureFormat(self, fmt): super(ConfigureStandard, self).configureFormat(fmt) import logging + import sys class SatFormatter(logging.Formatter): u"""Formatter which manage SàT specificities""" @@ -287,7 +292,12 @@ s = super(SatFormatter, self).format(record) if do_color: s = ConfigureStandard.ansiColors(record.levelname, s) - return s + if sys.platform == "android": + # FIXME: dirty hack to workaround android encoding issue on log + # need to be fixed properly + return s.encode('ascii', 'ignore') + else: + return s self.formatterClass = SatFormatter diff -r c02f96756d5c -r 0931b5a6213c src/core/sat_main.py --- a/src/core/sat_main.py Sun Dec 04 18:16:37 2016 +0100 +++ b/src/core/sat_main.py Sun Dec 04 18:16:48 2016 +0100 @@ -150,13 +150,20 @@ ui_contact_list.ContactList(self) ui_profile_manager.ProfileManager(self) self.initialised.callback(None) - log.info(_("Backend is ready")) + log.info(_(u"Backend is ready")) def _import_plugins(self): """Import all plugins found in plugins directory""" - import sat.plugins - plugins_path = os.path.dirname(sat.plugins.__file__) - plug_lst = [os.path.splitext(plugin)[0] for plugin in map(os.path.basename, glob(os.path.join(plugins_path, "plugin*.py")))] + if sys.platform == "android": + # FIXME: android hack to load plugins from proper path + # TODO: move this in a separate module and/or use sat.conf to specify path + plugins_path = "/data/data/org.goffi.cagou.cagou/files/sat/plugins" + plugin_glob = "plugin*.pyo" + else: + import sat.plugins + plugins_path = os.path.dirname(sat.plugins.__file__) + plugin_glob = "plugin*.py" + plug_lst = [os.path.splitext(plugin)[0] for plugin in map(os.path.basename, glob(os.path.join(plugins_path, plugin_glob)))] plugins_to_import = {} # plugins we still have to import for plug in plug_lst: plugin_path = 'sat.plugins.' + plug diff -r c02f96756d5c -r 0931b5a6213c src/core/xmpp.py --- a/src/core/xmpp.py Sun Dec 04 18:16:37 2016 +0100 +++ b/src/core/xmpp.py Sun Dec 04 18:16:48 2016 +0100 @@ -34,6 +34,7 @@ import time import calendar import uuid +import sys class SatXMPPClient(wokkel_client.XMPPClient): @@ -42,6 +43,17 @@ def __init__(self, host_app, profile, user_jid, password, host=None, port=C.XMPP_C2S_PORT, max_retries=C.XMPP_MAX_RETRIES): # XXX: DNS SRV records are checked when the host is not specified. # If no SRV record is found, the host is directly extracted from the JID. + if sys.platform == "android": + # FIXME: temporary hack as SRV is not working on android + # TODO: remove this hack and fix SRV + log.info(u"FIXME: Android hack, ignoring SRV") + host = user_jid.host + hosts_map = host_app.memory.getConfig("android", "hosts_dict", {}) + if host in hosts_map: + log.info(u"using {host_to_use} for host {host_ori} as requested in config".format( + host_ori = host, + host_to_use = hosts_map[host])) + host = hosts_map[host] wokkel_client.XMPPClient.__init__(self, user_jid, password, host or None, port or C.XMPP_C2S_PORT) self.factory.clientConnectionLost = self.connectionLost self.factory.maxRetries = max_retries diff -r c02f96756d5c -r 0931b5a6213c src/tools/utils.py --- a/src/tools/utils.py Sun Dec 04 18:16:37 2016 +0100 +++ b/src/tools/utils.py Sun Dec 04 18:16:48 2016 +0100 @@ -25,6 +25,7 @@ log = getLogger(__name__) import datetime import time +import sys def clean_ustr(ustr): @@ -78,6 +79,9 @@ - date: ISO 8601 format date - tag: latest tag used in hierarchie """ + if sys.platform == "android": + # FIXME: workaround to avoid trouble on android, need to be fixed properly + return u"Cagou android build" from distutils.spawn import find_executable import subprocess KEYS=("node", "node_short", "branch", "date", "tag")