Warning
This documentation does not refer to the most recent version of Pylons. Current Documentation
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']