root/galaxy-central/eggs/Cheetah-2.2.2-py2.6-macosx-10.6-universal-ucs2.egg/Cheetah/SettingsManager.py @ 3

リビジョン 3, 10.1 KB (コミッタ: kohda, 14 年 前)

Install Unix tools  http://hannonlab.cshl.edu/galaxy_unix_tools/galaxy.html

行番号 
1import sys
2import os.path
3import copy as copyModule
4from ConfigParser import ConfigParser
5import re
6from tokenize import Intnumber, Floatnumber, Number
7from types import *
8import types
9import new
10import time
11from StringIO import StringIO # not cStringIO because of unicode support
12import imp                 # used by SettingsManager.updateSettingsFromPySrcFile()
13
14
15numberRE = re.compile(Number)
16complexNumberRE = re.compile('[\(]*' +Number + r'[ \t]*\+[ \t]*' + Number + '[\)]*')
17
18convertableToStrTypes = (StringType, IntType, FloatType,
19                         LongType, ComplexType, NoneType,
20                         UnicodeType)
21
22##################################################
23## FUNCTIONS ##
24
25def mergeNestedDictionaries(dict1, dict2, copy=False, deepcopy=False):
26    """Recursively merge the values of dict2 into dict1.
27
28    This little function is very handy for selectively overriding settings in a
29    settings dictionary that has a nested structure.
30    """
31
32    if copy:
33        dict1 = copyModule.copy(dict1)
34    elif deepcopy:
35        dict1 = copyModule.deepcopy(dict1)
36       
37    for key,val in dict2.items():
38        if dict1.has_key(key) and type(val) == types.DictType and \
39           type(dict1[key]) == types.DictType:
40           
41            dict1[key] = mergeNestedDictionaries(dict1[key], val)
42        else:
43            dict1[key] = val
44    return dict1
45   
46def stringIsNumber(S):
47    """Return True if theString represents a Python number, False otherwise.
48    This also works for complex numbers and numbers with +/- in front."""
49
50    S = S.strip()
51   
52    if S[0] in '-+' and len(S) > 1:
53        S = S[1:].strip()
54   
55    match = complexNumberRE.match(S)
56    if not match:
57        match = numberRE.match(S)
58    if not match or (match.end() != len(S)):
59        return False
60    else:
61        return True
62       
63def convStringToNum(theString):
64    """Convert a string representation of a Python number to the Python version"""
65   
66    if not stringIsNumber(theString):
67        raise Error(theString + ' cannot be converted to a Python number')
68    return eval(theString, {}, {})
69
70
71class Error(Exception):
72    pass
73
74class NoDefault(object):
75    pass
76
77class ConfigParserCaseSensitive(ConfigParser):
78    """A case sensitive version of the standard Python ConfigParser."""
79   
80    def optionxform(self, optionstr):
81        """Don't change the case as is done in the default implemenation."""
82        return optionstr
83
84class _SettingsCollector(object):
85    """An abstract base class that provides the methods SettingsManager uses to
86    collect settings from config files and strings.
87
88    This class only collects settings it doesn't modify the _settings dictionary
89    of SettingsManager instances in any way.
90    """
91
92    _ConfigParserClass = ConfigParserCaseSensitive
93
94    def readSettingsFromModule(self, mod, ignoreUnderscored=True):
95        """Returns all settings from a Python module.
96        """
97        S = {}
98        attrs = vars(mod)
99        for k, v in attrs.items():
100            if (ignoreUnderscored and k.startswith('_')):
101                continue
102            else:
103                S[k] = v
104        return S
105       
106    def readSettingsFromPySrcStr(self, theString):
107        """Return a dictionary of the settings in a Python src string."""
108
109        globalsDict = {'True':(1==1),
110                       'False':(0==1),
111                       }
112        newSettings = {'self':self}
113        exec (theString+os.linesep) in globalsDict, newSettings       
114        del newSettings['self']
115        module = new.module('temp_settings_module')
116        module.__dict__.update(newSettings)
117        return self.readSettingsFromModule(module)
118
119    def readSettingsFromConfigFileObj(self, inFile, convert=True):
120        """Return the settings from a config file that uses the syntax accepted by
121        Python's standard ConfigParser module (like Windows .ini files).
122
123        NOTE:
124        this method maintains case unlike the ConfigParser module, unless this
125        class was initialized with the 'caseSensitive' keyword set to False.
126
127        All setting values are initially parsed as strings. However, If the
128        'convert' arg is True this method will do the following value
129        conversions:
130       
131        * all Python numeric literals will be coverted from string to number
132       
133        * The string 'None' will be converted to the Python value None
134       
135        * The string 'True' will be converted to a Python truth value
136       
137        * The string 'False' will be converted to a Python false value
138       
139        * Any string starting with 'python:' will be treated as a Python literal
140          or expression that needs to be eval'd. This approach is useful for
141          declaring lists and dictionaries.
142
143        If a config section titled 'Globals' is present the options defined
144        under it will be treated as top-level settings.       
145        """
146       
147        p = self._ConfigParserClass()
148        p.readfp(inFile)
149        sects = p.sections()
150        newSettings = {}
151
152        sects = p.sections()
153        newSettings = {}
154       
155        for s in sects:
156            newSettings[s] = {}
157            for o in p.options(s):
158                if o != '__name__':
159                    newSettings[s][o] = p.get(s,o)
160
161        ## loop through new settings -> deal with global settings, numbers,
162        ## booleans and None ++ also deal with 'importSettings' commands
163
164        for sect, subDict in newSettings.items():
165            for key, val in subDict.items():
166                if convert:
167                    if val.lower().startswith('python:'):
168                        subDict[key] = eval(val[7:],{},{})
169                    if val.lower() == 'none':
170                        subDict[key] = None
171                    if val.lower() == 'true':
172                        subDict[key] = True
173                    if val.lower() == 'false':
174                        subDict[key] = False
175                    if stringIsNumber(val):
176                        subDict[key] = convStringToNum(val)
177                       
178                ## now deal with any 'importSettings' commands
179                if key.lower() == 'importsettings':
180                    if val.find(';') < 0:
181                        importedSettings = self.readSettingsFromPySrcFile(val)
182                    else:
183                        path = val.split(';')[0]
184                        rest = ''.join(val.split(';')[1:]).strip()
185                        parentDict = self.readSettingsFromPySrcFile(path)
186                        importedSettings = eval('parentDict["' + rest + '"]')
187                       
188                    subDict.update(mergeNestedDictionaries(subDict,
189                                                           importedSettings))
190                       
191            if sect.lower() == 'globals':
192                newSettings.update(newSettings[sect])
193                del newSettings[sect]
194               
195        return newSettings
196
197
198class SettingsManager(_SettingsCollector):
199    """A mixin class that provides facilities for managing application settings.
200   
201    SettingsManager is designed to work well with nested settings dictionaries
202    of any depth.
203    """
204
205    def __init__(self):
206        super(SettingsManager, self).__init__()
207        self._settings = {}
208        self._initializeSettings()
209
210    def _defaultSettings(self):
211        return {}
212   
213    def _initializeSettings(self):
214        """A hook that allows for complex setting initialization sequences that
215        involve references to 'self' or other settings.  For example:
216              self._settings['myCalcVal'] = self._settings['someVal'] * 15       
217        This method should be called by the class' __init__() method when needed.       
218        The dummy implementation should be reimplemented by subclasses.
219        """
220       
221        pass
222
223    ## core post startup methods
224
225    def setting(self, name, default=NoDefault):
226        """Get a setting from self._settings, with or without a default value."""
227       
228        if default is NoDefault:
229            return self._settings[name]
230        else:
231            return self._settings.get(name, default)
232
233
234    def hasSetting(self, key):
235        """True/False"""
236        return key in self._settings
237
238    def setSetting(self, name, value):
239        """Set a setting in self._settings."""
240        self._settings[name] = value
241
242    def settings(self):
243        """Return a reference to the settings dictionary"""
244        return self._settings
245       
246    def copySettings(self):
247        """Returns a shallow copy of the settings dictionary"""
248        return copyModule.copy(self._settings)
249
250    def deepcopySettings(self):
251        """Returns a deep copy of the settings dictionary"""
252        return copyModule.deepcopy(self._settings)
253   
254    def updateSettings(self, newSettings, merge=True):
255        """Update the settings with a selective merge or a complete overwrite."""
256       
257        if merge:
258            mergeNestedDictionaries(self._settings, newSettings)
259        else:
260            self._settings.update(newSettings)
261
262
263    ## source specific update methods
264
265    def updateSettingsFromPySrcStr(self, theString, merge=True):
266        """Update the settings from a code in a Python src string."""
267       
268        newSettings = self.readSettingsFromPySrcStr(theString)
269        self.updateSettings(newSettings,
270                            merge=newSettings.get('mergeSettings',merge) )
271       
272   
273    def updateSettingsFromConfigFileObj(self, inFile, convert=True, merge=True):
274        """See the docstring for .updateSettingsFromConfigFile()
275
276        The caller of this method is responsible for closing the inFile file
277        object."""
278
279        newSettings = self.readSettingsFromConfigFileObj(inFile, convert=convert)
280        self.updateSettings(newSettings,
281                            merge=newSettings.get('mergeSettings',merge))
282
283    def updateSettingsFromConfigStr(self, configStr, convert=True, merge=True):
284        """See the docstring for .updateSettingsFromConfigFile()
285        """
286
287        configStr = '[globals]\n' + configStr
288        inFile = StringIO(configStr)
289        newSettings = self.readSettingsFromConfigFileObj(inFile, convert=convert)
290        self.updateSettings(newSettings,
291                            merge=newSettings.get('mergeSettings',merge))
292
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。