Latest Version: 0.9.6.2

Warning

This documentation does not refer to the most recent version of Pylons. Current Documentation

/Users/bbangert/Programming/Python/Pylonstrunk/pylons/util.py
0001"""Helpers object, RequestLocal object, and Paste Template config
0002
0003The util module provides the main Helper object used by Pylons.
0004
0005The RequestLocal thread-local is utilized by Pylons as the ``c`` object that
0006is available via ``pylons.c`` and is cleared every request by Pylons.
0007
0008PylonsTemplate is a Paste Template sub-class that configures the source
0009directory and default plug-ins for a new Pylons project.
0010"""
0011import sys
0012import os.path, gettext
0013
0014from paste.script.templates import Template
0015
0016import pylons
0017
0018from routes import threadinglocal
0019from paste.deploy.config import CONFIG
0020
0021def get_prefix(environ):
0022    prefix = environ['paste.config']['app_conf'].get('prefix', '')
0023    if not prefix:
0024        if environ.get('SCRIPT_NAME', '') != '':
0025            prefix = environ['SCRIPT_NAME']
0026    return prefix
0027
0028def class_name_from_module_name(module_name):
0029    """Takes a module name and returns the name of the class it defines.
0030
0031    If the module name contains dashes, they are replaced with underscores.
0032    
0033    Example::
0034    
0035        >>> class_name_from_module_name('with-dashes')
0036        'WithDashes'
0037        >>> class_name_from_module_name('with_underscores')
0038        'WithUnderscores'
0039        >>> class_name_from_module_name('oneword')
0040        'Oneword'
0041    
0042    """
0043    words = module_name.replace('-', '_').split('_')
0044    return ''.join([w.title() for w in words])
0045
0046
0047class RequestLocal(object):
0048    """This object emulates a dict and supports the full set of dict functions
0049    and operations.
0050    
0051    Internally, the dict is attached to a threading local object and
0052    all access is passed through to the thread-safe object.
0053    
0054    This difference means that the object must be initialized per-thread
0055    with a _clear() call before the object can be used, and it should be
0056    _clear()'ed every request call.
0057    
0058    The RequestLocal object also support attribute assignment, which is
0059    then internally stored as if they used item assignment. Attribute
0060    get is also supported, and is used to 'get' the name requested. Unlike
0061    normal attribute access, this will return an empty string if the
0062    attribute does not exist.
0063    """
0064    def __init__(self):
0065        self.__dict__['_local'] = threadinglocal.local()
0066
0067    def __getattr__(self, name):
0068        if name.startswith('_'):
0069            return object.__getattribute__(self, name)
0070        else:
0071            try:
0072                result = getattr(self._local.request, name)
0073            except AttributeError:
0074                result = self._local.request.get(name, '')
0075            return result
0076
0077    def __setattr__(self, key, value):
0078        if key.startswith('_'):
0079            raise AttributeError("You cannot set attributes begining with '_' \
0080on  the 'temp' object use temp['%s'] instead"%key)
0081            #object.__setattr__(self, key, value)
0082        else:
0083            self.__setitem__(key, value)
0084
0085    def __len__(self):
0086        return self._local.request.__len__()
0087
0088    def __getitem__(self, key):
0089        return self._local.request.__getitem__(key)
0090
0091    def __setitem__(self, key, value):
0092        self._local.request.__setitem__(key, value)
0093
0094    def __delitem__(self, key):
0095        self._local.request.__delitem__(key)
0096
0097    def __iter__(self):
0098        return self._local.request.__iter__()
0099
0100    def __contains__(self, item):
0101        return self._local.request.__contains__(item)
0102
0103    def _clear(self):
0104        self._local.request = {}
0105
0106    def __repr__(self):
0107        return self._local.request.__repr__()
0108
0109class LanguageError(Exception):
0110    """Exception raised when a problem occurs with changing languages"""
0111    pass
0112
0113class _Translator(object):
0114    """An empty gettext translator which just returns the original string"""
0115    def gettext(self, value):
0116        return value
0117
0118class Helpers(object):
0119    def __init__(self, **_pylons):
0120        self.__dict__['_local'] = RequestLocal()
0121        self.__dict__['_pylons'] = _pylons
0122
0123    def __call__(self):
0124        """Initialize Helpers object for request with helpers module/object
0125        
0126        When called, the Helpers object will return itself, after initializing
0127        itself for the current thread/request. It is intended to be run at the
0128        begginning of every request to clear the thread local it uses and setup
0129        the helpers space that will be used for fetching helper names as well
0130        as translation.
0131        """
0132        self.__dict__['_local']._clear()
0133        project_name = CONFIG['app_conf']['package']
0134        try:
0135            helpers_name = project_name + '.config.helpers'
0136            __import__(helpers_name)
0137        except:
0138            helpers_name = project_name + '.lib.helpers'
0139            __import__(helpers_name)
0140        helpers = sys.modules[helpers_name]
0141        self.__dict__['_local'].helpers = helpers
0142        self.__dict__['_local'].translator = _Translator()
0143        self.__dict__['_local'].config = CONFIG
0144        if CONFIG['app_conf'].has_key('lang'):
0145            self.set_lang(CONFIG['app_conf']['lang'])
0146        else:
0147            self.__dict__['_local'].lang = None
0148        return self
0149
0150    def __getattr__(self, name):
0151        if hasattr(self.__dict__['_local'].helpers, name):
0152            return getattr(self.__dict__['_local'].helpers, name)
0153        elif name in self.__dict__['_local'].keys() and name != '_local' and               len(str(name))>0 and str(name)[0] != '_':
0155            return getattr(self.__dict__['_local'],name)
0156        else:
0157            raise AttributeError('No such helper %s'%repr(name))
0158
0159    def __setattr__(self, name, value):
0160        if name not in ['lang']:
0161            raise AttributeError("Helper attributes cannot be set. You should \
0162use the context object 'c' to store conext information.")
0163        else:
0164            self.set_lang(value)
0165
0166    def log(self, msg):
0167        """Log a message to the output log."""
0168        pylons.request.environ['wsgi.errors'].write('=> %s\n'%str(msg))
0169
0170    def translate(self, value):
0171        """Deprecated, use _()"""
0172        raise NotImplementedError('Use h._() instead')
0173
0174    def _(self, value):
0175        """Mark a string for translation
0176        
0177        Mark a string to be internationalised as follows:
0178        
0179            h._('This should be in lots of langauges')
0180        """
0181        return self.__dict__['_local'].translator.gettext(value)
0182
0183    def set_lang(self, lang):
0184        """Set the language used"""
0185        project_name = CONFIG['app']['package']
0186        self.__dict__['_local'].lang = lang
0187        if lang is None:
0188            self.__dict__['_local'].translator = _Translator()
0189        else:
0190            from pkg_resources import resource_string, resource_stream,                   resource_exists, resource_filename
0192            from pylons.i18n.translation import egg_translation
0193            catalog_path = os.path.join('i18n', lang, 'LC_MESSAGES')
0194            if not resource_exists(project_name, catalog_path):
0195                raise LanguageError('Langauge catalog %s not found' %                                       os.path.join(project_name, catalog_path))
0197            self.__dict__['_local'].translator =                   egg_translation(project_name, lang=catalog_path)
0199
0200    def get_lang(self):
0201        return self.__dict__['_local'].lang
0202
0203
0204class PylonsTemplate(Template):
0205    _template_dir = 'templates/paster_template'
0206    summary = 'Pylons application template'
0207    egg_plugins = ['Pylons', 'WebHelpers']
0208
0209__all__ = ['RequestLocal', 'Helpers']
0210__pudge_all__ = ['RequestLocal', 'Helpers', 'PylonsTemplate']

Top