Source code for soma.application

# -*- coding: utf-8 -*-

#  This software and supporting documentation are distributed by
#      Institut Federatif de Recherche 49
#      CEA/NeuroSpin, Batiment 145,
#      91191 Gif-sur-Yvette cedex
#      France
#
# This software is governed by the CeCILL-B license under
# French law and abiding by the rules of distribution of free software.
# You can  use, modify and/or redistribute the software under the
# terms of the CeCILL-B license as circulated by CEA, CNRS
# and INRIA at the following URL "http://www.cecill.info".
#
# As a counterpart to the access to the source code and  rights to copy,
# modify and redistribute granted by the license, users are provided only
# with a limited warranty  and the software's author,  the holder of the
# economic rights,  and the successive licensors  have only  limited
# liability.
#
# In this respect, the user's attention is drawn to the risks associated
# with loading,  using,  modifying and/or developing or reproducing the
# software by the user in light of its specific status of free software,
# that may mean  that it is complicated to manipulate,  and  that  also
# therefore means  that it is reserved for developers  and  experienced
# professionals having in-depth computer knowledge. Users are therefore
# encouraged to load and test the software's suitability as regards their
# requirements in conditions enabling the security of their systems and/or
# data to be ensured and,  more generally, to use and operate it in the
# same conditions as regards security.
#
# The fact that you are presently reading this means that you have had
# knowledge of the CeCILL-B license and that you accept its terms.

'''
* author: Yann Cointepas
* organization: NeuroSpin
* license: `CeCILL B <http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html>`_
'''

from __future__ import absolute_import
__docformat__ = "restructuredtext en"


import os
import sys
import platform
import traceback
from os.path import dirname

os.environ['ETS_TOOLKIT'] = 'qt4'
try:
    from enthought.traits.api import ReadOnly, Directory, ListStr, Instance
except ImportError:
    from traits.api import ReadOnly, Directory, ListStr, Instance

from soma.singleton import Singleton
from soma.controller import Controller

#-------------------------------------------------------------------------


[docs]class Application(Singleton, Controller): '''Any program using soma should create an Application instance to manage its configuration and to store any kind of value that have to be global to the program.''' name = ReadOnly(desc='Name of the application') version = ReadOnly() plugin_modules = ListStr( desc='List of Python module to load after application configuration') def __singleton_init__(self, name=None, version=None, *args, **kwargs): '''Replaces __init__ in Singleton.''' super(Application, self).__singleton_init__(*args, **kwargs) # Warning : Traits bug # Using the trait Directory() might instanciate a QApplication (seems to depend on the # traits release). If it is declared in the class, the QApplication is instanciated at # module importation which prevent to customize QApplication. self.add_trait('install_directory', Directory( desc='Base directory where the application is installed')) self.add_trait('user_directory', Directory( desc='Base directory where user specific information can be find')) self.add_trait('application_directory', Directory( desc='Base directory where application specifc information can be find')) self.add_trait('site_directory', Directory( desc='Base directory where site specifc information can be find')) self._controller_factories = None if name is None: name = os.path.basename(sys.argv[0]) self.name = name self.version = version self.loaded_plugin_modules = {}
[docs] def initialize(self): '''This method must be called once to setup the application.''' self.install_directory = dirname(dirname(dirname(__file__))) homedir = os.getenv('HOME') if not homedir: homedir = '' if platform.system() == 'Windows': homedir = os.getenv('USERPROFILE') if not homedir: homedir = os.getenv('HOMEPATH') if not homedir: homedir = '\\' drive = os.getenv('HOMEDRIVE') if not drive: drive = os.getenv('SystemDrive') if not drive: drive = os.getenv('SystemRoot') if not drive: drive = os.getenv('windir') if drive and len(drive) >= 2: drive = drive[:2] else: drive = '' homedir = drive + homedir if homedir and os.path.exists(homedir): self.user_directory = homedir # Load early plugin modules for plugin_module in self.plugin_modules: module = self.load_plugin_module(plugin_module) if module is not None: self.loaded_plugin_modules[plugin_module] = module init = getattr( module, 'call_before_application_initialization', None) if init is not None: init(self) appdir = os.path.normpath( os.path.dirname(os.path.dirname(sys.argv[0]))) if os.path.exists(appdir): self.application_directory = appdir sitedir = os.path.join('/etc', self.name) if os.path.exists(sitedir): self.site_directory = sitedir # Load plugin modules for plugin_module in self.plugin_modules: module = self.loaded_plugin_modules.get(plugin_module) if module is None: module = self.load_plugin_module(plugin_module) if module is not None: self.loaded_plugin_modules[plugin_module] = module init = getattr( module, 'call_after_application_initialization', None) if init is not None: init(self)
[docs] @staticmethod def load_plugin_module(plugin_module): '''This method loads a plugin module. It imports the module without raising an exception if it fails.''' try: __import__(plugin_module, level=0) return sys.modules[plugin_module] except Exception: # Python 2.6 hack : print_last may fail here (maybe due to threads management) # traceback.print_last() exceptionType, exceptionValue, exceptionTraceback = sys.exc_info() traceback.print_exception( exceptionType, exceptionValue, exceptionTraceback) return None