Author: reinhard Date: 2008-07-30 03:16:46 -0500 (Wed, 30 Jul 2008) New Revision: 9890
Added: trunk/gnue-common/src/lib/modules.py Modified: trunk/gnue-common/src/base/i18n.py Log: Added some general module magic functions. Modified: trunk/gnue-common/src/base/i18n.py =================================================================== --- trunk/gnue-common/src/base/i18n.py 2008-07-30 08:11:36 UTC (rev 9889) +++ trunk/gnue-common/src/base/i18n.py 2008-07-30 08:16:46 UTC (rev 9890) @@ -35,6 +35,7 @@ import sys from gnue import paths +from gnue.common.lib import modules __all__ = ['language', 'encoding', 'outconv', 'utranslate', 'translate', 'get_language', 'get_encoding', 'get_user_locale', @@ -45,9 +46,6 @@ # Global variables # ----------------------------------------------------------------------------- -__modules = {} # Modules by filename -__catalogs = {} # Message catalogs by domain:language - language = None encoding = None @@ -68,45 +66,49 @@ # ----------------------------------------------------------------------------- -# Find a module from filename +# Translate a message and return unicode # ----------------------------------------------------------------------------- -def __find_module(filename): - if __modules.has_key(filename): - return __modules[filename] - for mod in sys.modules.values(): - if hasattr(mod, '__file__'): - # mod.__file__ can be .pyc if the module is already compiled - mod_filename = mod.__file__ - if mod_filename.endswith('c'): - mod_filename = mod_filename[:-1] - if os.path.normcase(mod_filename) == os.path.normcase(filename): - __modules[filename] = mod - return mod +def utranslate(message): + """ + Translates a message and returns a unicode string. This function is + available as the builtin function "u_()". + """ + caller_module = modules.caller_module() + if not __DOMAINS.has_key(caller_module): + # Look for translation domain to use for the caller module. + domain = modules.find_global('__gettext_domain__') -# ----------------------------------------------------------------------------- -# Find the correct translation catalog -# ----------------------------------------------------------------------------- + if domain is None: + # For gnue.common.foo.bar, try gnue-common-foo-bar, + # gnue-common-foo, gnue-common and gnue (in that order). + parts = caller_module.split('.') + while parts: + try_domain = '-'.join(parts) + if __find_catalog(try_domain) is not None: + domain = try_domain + break + del parts[-1] -def __find_catalog(): + __DOMAINS[caller_module] = domain - # find out the filename of the calling function - caller_file = (sys._getframe(2)).f_code.co_filename + domain = __DOMAINS[caller_module] + if domain is None: + return message - # find out the module name - caller_module = __find_module(caller_file) + catalog = __find_catalog(domain) + if catalog is None: + return message - if caller_module is None: - return None + return catalog.ugettext(message) - # make 'gnue-common' from 'gnue.common.foo.bar' - module_name = caller_module.__name__.replace('.', '-', 1) - i = module_name.find('.') - domain = module_name[:i] +# ----------------------------------------------------------------------------- - if __catalogs.has_key(domain + ':' + language): - return __catalogs[domain + ':' + language] +def __find_catalog(domain): + + if __CATALOGS.has_key(domain + ':' + language): + return __CATALOGS[domain + ':' + language] else: try: catalog = gettext.translation(domain, paths.data + '/share/locale', @@ -114,29 +116,12 @@ except: catalog = None - __catalogs[domain + ':' + language] = catalog + __CATALOGS[domain + ':' + language] = catalog return catalog # ----------------------------------------------------------------------------- -# Translate a message and return unicode -# ----------------------------------------------------------------------------- - -def utranslate(message): - """ - Translates a message and returns a unicode string. This function is - available as the builtin function "u_()". - """ - catalog = __find_catalog() - - if catalog is None: - return message - - return catalog.ugettext(message) - - -# ----------------------------------------------------------------------------- # Translate a message and return local encoding # ----------------------------------------------------------------------------- @@ -150,6 +135,14 @@ # ----------------------------------------------------------------------------- +# Cache variables +# ----------------------------------------------------------------------------- + +__DOMAINS = {} # Domains by module name +__CATALOGS = {} # Message catalogs by domain:language + + +# ----------------------------------------------------------------------------- # Get the current language # ----------------------------------------------------------------------------- Added: trunk/gnue-common/src/lib/modules.py =================================================================== --- trunk/gnue-common/src/lib/modules.py (rev 0) +++ trunk/gnue-common/src/lib/modules.py 2008-07-30 08:16:46 UTC (rev 9890) @@ -0,0 +1,132 @@ +# GNU Enterprise Common Library - Module inspection +# +# Copyright 2001-2008 Free Software Foundation +# +# This file is part of GNU Enterprise +# +# GNU Enterprise is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2, or (at your option) any later version. +# +# GNU Enterprise is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with program; see the file COPYING. If not, +# write to the Free Software Foundation, Inc., 59 Temple Place +# - Suite 330, Boston, MA 02111-1307, USA. +# +# $Id$ + +""" +Functions to find out about the module of the caller. + +This module extends the standard Python inspect module. +""" + +import inspect +import sys + +__all__ = ['caller_module', 'find_global'] + + +# ============================================================================= +# Find out about the caller module +# ============================================================================= + +# ----------------------------------------------------------------------------- +# Return the name of the calling module +# ----------------------------------------------------------------------------- + +def caller_module(): + """ + Return the name of the module that called the function from which this + function was called. + + Simple example:: + def myfunc(): + # This will print the name of the module from which myfunc() + # was called. + print caller_module() + + The first caller outside the current module will be searched, everything + within the same module will be skipped:: + def myfunc(): + __internal_func() + def otherfunc(): + __internal_func() + def __internal_func(): + # This will print the name of the module from which either myfunc() + # or otherfunc() was called + print caller_module() + + @return: name of the module + @rtype: string + """ + + frame = inspect.currentframe() + # Skip everything from our own module. + while frame.f_globals['__name__'] == __name__: + frame = frame.f_back + # Skip everything from our caller. + while frame.f_back.f_globals['__name__'] == frame.f_globals['__name__']: + frame = frame.f_back + return frame.f_back.f_globals['__name__'] + + +# ----------------------------------------------------------------------------- +# Find a global variable in the calling module or one of its parent packages +# ----------------------------------------------------------------------------- + +def find_global(name): + """ + Find a global variable in the calling function's calling module or one of + its parent packages. + + This is useful to introduce "magic" variables in modules that modify the + behaviour of an imported function. + + For example, if we have a module like this:: + # Module logfile + from gnue.common.lib.module import find_global + def log(message): + filename = find_global('__logfilename__') + f = open(filename, 'a') + f.write(message) + f.close() + + Then a module can use that like that:: + # Module mypkg.mymodule + from logfile import log + __logfilename__ = '/var/log/mylog' + log('Initializing module') + + But the magic variable can also be defined in the parent package:: + # Module mypkg + __logfilename__ = '/var/log/mylog' # Valid also for all modules + # contained in this package + + # Module mypkg.mymodule + from logfile import log + log('Initializing mymodule') + + # Module mypkg.othermodule + from logfile import log + log('Initializing othermodule') + + @param name: Variable name to look for + @type name: string + @return: Value of the variable, or None if not found + @rtype: any + """ + + parts = caller_module().split('.') + while parts: + mod = sys.modules['.'.join(parts)] + if hasattr(mod, name): + return getattr(mod, name) + del parts[-1] + return None Property changes on: trunk/gnue-common/src/lib/modules.py ___________________________________________________________________ Name: svn:keywords + Id _______________________________________________ commit-gnue mailing list commit-gnue@gnu.org http://lists.gnu.org/mailman/listinfo/commit-gnue