Changeset 199
- Timestamp:
- Tue Mar 7 16:39:05 2006
- Files:
-
- trunk/tests/doctests/txt/xix-utils-config-SpanningLines.txt (added)
- trunk/tests/doctests/txt/xix-utils-python-Curried.txt (added)
- trunk/tests/doctests/txt/xix-utils-config-Sections.txt (added)
- trunk/tests/doctests/utils/python.py (modified) (diff)
- trunk/tests/doctests/utils/config.py (modified) (diff)
- trunk/utiltests.py (modified) (diff)
- trunk/xix/utils/decor.py (modified) (diff)
- trunk/xix/utils/console.py (modified) (diff)
- trunk/xix/utils/config.py (modified) (diff)
- trunk/xix/utils/python.py (modified) (diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
trunk/tests/doctests/utils/python.py
r159 r199 1 from xix.utils.python import ModuleWrapper 1 ##from xix.utils.python import ModuleWrapper 2 # 2 3 3 class ModuleWrapperTest: 4 def importAll(self): 5 '''Example Usage: 4 class DummyTest: 5 """ 6 >>> print 1 7 1 8 """ 6 9 7 >>> "uppercase" not in locals() 8 True 9 >>> wrapper = ModuleWrapper("string") 10 >>> wrapper.importAll() 11 >>> print uppercase 12 ABCDEFGHIJKLMNOPQRSTUVWXYZ 13 ''' 14 def importModule(self): 15 '''Example Usage: 16 17 >>> "sre" not in locals() 18 True 19 >>> wrapper = ModuleWrapper("sre") 20 >>> wrapper.importModule() 21 >>> type(sre) 22 <type 'module'> 23 ''' 24 def importNames(self, *names): 25 '''Example Usage: 26 27 >>> "uppercase" not in locals() and "upper" not in locals() 28 True 29 >>> wrapper = ModuleWrapper("string") 30 >>> wrapper.importNames("uppercase", "upper") 31 >>> print uppercase 32 ABCDEFGHIJKLMNOPQRSTUVWXYZ 33 >>> print upper("lower") 34 LOWER 35 ''' 10 #class ModuleWrapperTest: 11 # def importAll(self): 12 # '''Example Usage: 13 # 14 # >>> "uppercase" not in locals() 15 # True 16 # >>> wrapper = ModuleWrapper("string") 17 # >>> wrapper.importAll() 18 # >>> print uppercase 19 # ABCDEFGHIJKLMNOPQRSTUVWXYZ 20 # ''' 21 # def importModule(self): 22 # '''Example Usage: 23 # 24 # >>> "sre" not in locals() 25 # True 26 # >>> wrapper = ModuleWrapper("sre") 27 # >>> wrapper.importModule() 28 # >>> type(sre) 29 # <type 'module'> 30 # ''' 31 # def importNames(self, *names): 32 # '''Example Usage: 33 # 34 # >>> "uppercase" not in locals() and "upper" not in locals() 35 # True 36 # >>> wrapper = ModuleWrapper("string") 37 # >>> wrapper.importNames("uppercase", "upper") 38 # >>> print uppercase 39 # ABCDEFGHIJKLMNOPQRSTUVWXYZ 40 # >>> print upper("lower") 41 # LOWER 42 # ''' -
trunk/tests/doctests/utils/config.py
r159 r199 7 7 8 8 from xix.utils.config import Config, ConfigLoader, ConfigFactory, configFactory 9 from xix.utils.config import ModuleWrapper 9 #from xix.utils.config import ModuleWrapper 9 9 10 10 # pydoc unit tests … … 14 14 def __init__(self, data): 15 15 self.data = data 16 self.lines = [(line + '\n') for line in data.split('\n')] 16 17 def read(self): 17 18 return self.data 19 def readline(self): 20 if self.lines: 21 next = self.lines.pop(0) 22 return next 18 23 19 24 class ConfigLoaderTest: … … 99 104 Traceback (most recent call last): 100 105 ... 101 ConfigLoaderException: Internal exception while trying to convert not good dude -- Cannot resolve type : not good dude. 102 """ 103 def example_someTypesNotSupported(self): 104 """ 105 Not all types are supported: 106 107 >>> fd = File("foo.bar=type") 108 >>> loader = ConfigLoader() 109 >>> loader.load(fd) 110 Traceback (most recent call last): 111 ... 112 ConfigLoaderException: Unsupported type: <type 'type'>. 113 """ 114 def example_moduleWrapper(self): 115 """ 116 We can also get a module wrapper ... 117 118 >>> fd = File("foo.bar=xix.utils.string") 119 >>> loader = ConfigLoader() 120 >>> cfg = loader.load(fd) 121 >>> from xix.utils.interfaces import IModuleWrapper 122 >>> IModuleWrapper.providedBy(cfg.foo.bar) 123 True 106 ConfigLoaderException: Exeception occurred evaluating: not good dude 124 107 """ 108 # def example_someTypesNotSupported(self): 109 # """ 110 # Not all types are supported: 111 # 112 # >>> fd = File("foo.bar=type") 113 # >>> loader = ConfigLoader() 114 # >>> loader.load(fd) 115 # Traceback (most recent call last): 116 # ... 117 # ConfigLoaderException: Unsupported type: <type 'type'>. 118 # """ 119 # def example_moduleWrapper(self): 120 # """ 121 # We can also get a module wrapper ... 122 # 123 # >>> fd = File("foo.bar=xix.utils.string") 124 # >>> loader = ConfigLoader() 125 # >>> cfg = loader.load(fd) 126 # >>> from xix.utils.interfaces import IModuleWrapper 127 # >>> IModuleWrapper.providedBy(cfg.foo.bar) 128 # True 129 # """ 125 130 126 131 -
trunk/utiltests.py
r193 r199 1 1 import xix.utils.config 2 2 import xix.utils.console 3 import xix.utils.decor 3 4 import xix.utils.string 4 5 import xix.utils.rules … … 14 15 xix.utils.config, 15 16 xix.utils.console, 17 xix.utils.decor, 16 18 xix.utils.string, 17 19 xix.utils.rules, -
trunk/xix/utils/decor.py
r177 r199 5 5 ''' 6 6 7 from xix.utils.python import allexcept7 from xix.utils.python import Curried 7 7 import time, inspect 8 8 9 import sys 10 9 11 __revision__ = '$Id$' 10 12 … … 14 16 __copyright__ = 'Copyright (C) 2005, Drew Smathers' 15 17 16 def timedfunction(function): 17 '''This decorator time's calls to function and prints 18 to standard out. 19 ''' 20 def wrapper(*args, **kwargs): 21 before = time.time() 22 result = function(*args, **kwargs) 23 after = time.time() 24 print '%s took %f s to complete' % \ 25 (function.__name__, after - before) 26 return result 27 # We want the wrapper (which will replace the wrappee) 28 # to be transparent as much as possible. 29 wrapper.__dict__.update(function.__dict__) 30 wrapper.__doc__ = function.__doc__ 31 wrapper.__name__ = function.__name__ 18 19 def _wrapup(wrapper, func): 20 wrapper.__dict__.update(func.__dict__) 21 wrapper.__doc__ = func.__doc__ 22 wrapper.__name__ = func.__name__ 32 23 return wrapper 33 24 34 ########################################################################## 35 # Curryable functions, methods 36 ########################################################################## 37 38 class CannotCurryException(Exception): 39 ''' 40 Raise when trying to build a curryable function with mixed argument 41 dimensions (keyword and positional) 42 ''' 43 pass 44 # we can build a decorator that makes a function curryable 45 46 def curryable(function): 47 '''My magnus opus of decorators ;) 48 This decorator makes the wrapped function curryable - with 49 positional or keyword arguments only - no mixing folks. 50 ''' 51 class _CurriedFunction: 52 def __init__(self, function, pargs=None, kwargs=None, nargs=None, posonly=False): 53 self._function = function 54 self._nargs = nargs 55 if posonly or pargs: 56 self._curried = pargs or [] 57 self._posonly = True 58 else: 59 self._curried = kwargs or {} 60 self._posonly = False 61 if self._nargs is None: 62 self._nargs = len(inspect.getargspec(self._function)[0]) - \ 63 (0,1)[inspect.ismethod(self._function)] 64 65 def __call__(self, *pargs, **kwargs): 66 if self._posonly and kwargs: 67 raise TypeError, "This curryable instance accepts only positional arguments" 68 if not self._posonly and pargs: 69 raise TypeError, "This curryable instance accepts only keyword arguments" 70 if (self._posonly): 71 curried = self._curried + list(pargs) 72 if len(curried) == self._nargs: 73 return self._function(*tuple(curried)) 74 elif len(curried) > self._nargs: 75 raise TypeError, ("curryable accepts at most %d positional arguments (%d given)" % 76 (self._nargs - len(self._curried), len(pargs))) 77 else: 78 new = _CurriedFunction(self._function, pargs=curried, nargs=self._nargs) 79 return new 80 else: 81 curried = dict(self._curried) 82 curried.update(kwargs) 83 if len(curried) == self._nargs: 84 return self._function(**dict(curried)) 85 elif len(curried) > self._nargs: 86 raise TypeError, ("curryable accepts at most %d keyword arguments (%d given)" % 87 (self._nargs - len(self._curried), len(pargs))) 88 else: 89 new = _CurriedFunction(self._function, kwargs=curried, nargs=self._nargs) 90 return new 91 25 26 def curryable(func): 27 """curryable wrapper - syntax suger for CurriedCallable. 28 29 Example Usage: 30 31 >>> @curryable 32 ... def something(a, b, c, d=23, e=32): 33 ... return a, b, c, d, e 34 ... 35 >>> curried = something() 36 >>> curried = something(d=56) 37 >>> print curried(1,2,3) 38 (1, 2, 3, 56, 32) 39 """ 92 40 def wrapper(*args, **kwargs): 93 if args and kwargs: 94 raise CannotCurryException, "Curryable functions can contain only positional " +\ 95 "or keyword arguments (not both)" 96 if args: curried = _CurriedFunction(function, posonly=True) 97 else: curried = _CurriedFunction(function, posonly=False) 41 curried = Curried(func) 98 42 return curried(*args, **kwargs) 99 wrapper.__dict__.update(function.__dict__) 100 wrapper.__doc__ = function.__doc__ 101 wrapper.__name__ = function.__name__ 102 return wrapper 43 return _wrapup(wrapper, func) 103 44 104 #__all__ = allexcept('time', 'inspect', 'allexcept')105 45 -
trunk/xix/utils/console.py
r177 r199 105 105 return message 106 106 code_string = ';'.join([str(code) for code in codes]) 107 return '\033[%sm%s\033[%sm' % (code_string, message, RESET) 107 return '\033[%sm%s\033[%sm' % (code_string, message, RESET) 108 109 class FormatFactory: 110 """Example Usage: 111 112 >>> factory = FormatFactory() 113 >>> factory['a'] = Format() 114 >>> factory['b'] = Format() 115 >>> factory['a'].format_on = False 116 >>> print int(factory['a'].format_on), int(factory['b'].format_on) 117 0 1 118 """ 119 120 def __init__(self): 121 self._reg = {} 122 123 def __getitem__(self, name): 124 return self._reg[name] 125 126 def __setitem__(self, name, fmt): 127 if self._reg.has_key(name): 128 raise ValueError, 'Format named %s already registered' % name 129 self._reg[name] = fmt 108 130 109 131 format = Format() 132 formatFactory = FormatFactory() 110 133 111 134 __all__ = setAll([], locals(), 'setAll', 'k', 'v') -
trunk/xix/utils/config.py
r193 r199 38 38 39 39 1. Cascading configurations 40 2. Object loader casting41 3. Textual substitution in configuration:42 ex.43 foo.world="World"44 foo.greeting="Hello " + $foo.world45 46 foo.lazy=1 + $foo.eval47 foo.eval=048 40 49 41 ''' 50 42 51 43 from xix.utils.interfaces import IConfig, IConfigLoader, IConfigFactory 52 from xix.utils.interfaces import IModuleWrapper 44 #from xix.utils.interfaces import IModuleWrapper 52 44 from xix.utils.comp.interface import providedBy, implements, classProvides 53 45 from xix.utils.python import allexcept 54 from xix.utils.python import ModuleWrapper 46 #from xix.utils.python import ModuleWrapper 54 46 from xix.utils.python import getCallersGlobals 55 47 import warnings … … 62 54 __version__ = '$Revision$'[11:-2] 63 55 56 sectionHeader = re.compile('^(\[+)([^\[\]]*)(\]+)\s*$').search 57 keyValue = re.compile('^([^=]+)=(.+)$').search 58 64 59 class ConfigException(Exception): 65 60 '''Raised when error directly tied to configuration occurs. … … 145 140 pass 146 141 147 142 143 ############ Builtin plugins to ConfigLoader## 148 144 def _unixpath(path): 149 145 return path.replace('/', os.path.sep) 150 146 147 def _replace(name): 148 _loader.append((_chain, name)) 149 ############################################### 150 151 class _StringFile: 152 153 def __init__(self, data): 154 self.data = data 155 self.lines = [(line + '\n') for line in data.split('\n')] 156 157 def read(self): 158 return self.data 159 160 def readline(self): 161 if self.lines: 162 return self.lines.pop(0) 163 return '' 164 165 BADLINE = 'Malformed line found in configuration: %s' 151 166 152 167 class ConfigLoader: … … 157 172 158 173 plugins = { 174 '_chain' : None, # Do not reference me directly 175 '_loader' : None, # Do not reference me directly 159 176 'path' : _unixpath, 177 '_' : _replace, 160 178 } 161 179 162 def load(self, fd):180 def load(self, data): 162 180 ''' 163 181 Example usage: 164 182 165 >>> class File: 166 ... def read(self): 167 ... return """ 183 >>> data = """ 168 184 ... foo.bar=123 169 185 ... foo.baz='hello world' 170 186 ... foo.foo.nested.pi=3.14 171 187 ... """ 172 ...173 >>> fd = File()174 188 >>> loader = ConfigLoader() 175 >>> cfg = loader.load( fd)189 >>> cfg = loader.load(data) 175 189 >>> print cfg.foo.bar, cfg.foo.baz, cfg.foo.foo.nested.pi 176 190 123 hello world 3.14 177 191 ''' 192 if hasattr(data, 'read'): 193 fd = data 194 else: 195 fd = _StringFile(data) 178 196 cfg = Config() 179 for line in (fd.read().split('\n')): 180 try: 181 if line[0] == "#": continue 182 if line.split() == []: continue 183 except: continue 197 self.replacement = [] 198 self.plugins['_loader'] = self 199 chainPrefixStack = [] 200 line = fd.readline() 201 prev = '' 202 while line: 203 line = line[:-1] 184 204 try: 185 cfg_chain = line.split("=")[0] 186 cfg_val = line.split("=")[1] 187 cfg_chain = cfg_chain.split(".") 188 assert len(cfg_chain) > 0 205 if line[0] == "#": 206 line = fd.readline() 207 continue 208 if line.split() == []: 209 line = fd.readline() 210 continue 189 211 except: 190 raise ConfigLoaderException("Malformed line found in configuration: %s" % line) 191 try: 192 cast = self._caster(cfg_val) 193 cfg_val = cast(cfg_val) 194 except ConfigLoaderException, cle: 195 raise ConfigLoaderException(str(cle)) 196 except Exception, e: 197 raise ConfigLoaderException("Exeception occurred in loading: " + str(e)) 212 line = fd.readline() 213 continue 214 if line[-1] == '\\': # continue scanning next line 215 prev = prev + line[:-1] 216 line = fd.readline() 217 continue 218 else: # finish scanning mult lines, or single line 219 line = prev + line 220 prev = '' 221 if keyValue(line): 222 cfg_chain, cfg_val = self._handleAssignment(line, keyValue(line), _flat(chainPrefixStack)) 223 elif sectionHeader(line): 224 cfg_chain, cfg_val = self._handleSection(line, sectionHeader(line), chainPrefixStack) 225 else: 226 raise ConfigLoaderException, BADLINE % line 198 227 for node in cfg_chain: 199 228 if not _isvalidname(node): … … 203 232 "Config node %s does not map to valid Python name" % node); 204 233 self._updateConfig(cfg, cfg_chain, cfg_val) 234 line = fd.readline() 205 235 return cfg 206 236 237 def _handleAssignment(self, line, reSearchResults, chainPrefix=[]): 238 lhs = reSearchResults.groups()[0].strip() 239 cfg_chain = chainPrefix + lhs.split('.') 240 cfg_val = reSearchResults.groups()[1].strip() 241 self._chain = cfg_chain 242 if len(cfg_chain) == 0: 243 raise ConfigLoaderException, BADLINE % line 244 try: 245 cfg_val = cast(self, cfg_val) 246 except ConfigLoaderException, cle: 247 raise ConfigLoaderException(str(cle)) 248 except Exception, e: 249 raise ConfigLoaderException("Exeception occurred evaluating: " + cfg_val) 250 return cfg_chain, cfg_val 251 252 def _handleSection(self, line, reSearchResults, stack): 253 head, section, tail = reSearchResults.groups() 254 if len(head) != len(tail): 255 raise ConfigLoaderException, BADLINE % line 256 if len(head) > len(stack) + 1: 257 raise ConfigLoaderException, 'Subsection does not have parent: %s' % line 258 while len(stack) > len(head) - 1: 259 stack.pop() 260 cfg_chain = section.split('.') 261 stack.append(cfg_chain) 262 return cfg_chain, None 207 263 208 def _updateConfig(self, cfg, cfg_chain, cfg_value): 264 def _updateConfig(self, cfg, cfg_chain, cfg_value=None): 208 264 chain = list(cfg_chain) 209 265 name = '.'.join(cfg_chain) … … 219 275 if bound: 220 276 if chain and IConfig.providedBy(attr): 221 cfg = getattr(cfg, node) 222 else: 277 cfg = attr 278 elif not cfg_value is None: 279 # TODO - decide if we really want raise exception or allowing 280 # redefinition to make overlays easier. 223 281 raise ConfigLoaderException("Duplicate entry %s" % name) 224 282 else: 225 if chain :283 if chain or cfg_value is None: # TODO unit test for None case 225 283 child = Config() 226 284 setattr(cfg, node, child) … … 229 287 else: 230 288 setattr(cfg, node, cfg_value) 231 232 289 233 def _caster(self, s):234 namespace = {}235 try:236 try:237 # TODO - This is extremely unsafe - need an rexec238 exec("tipe = type(%s)" % s, namespace, namespace)239 tipe = namespace["tipe"]240 if tipe == int or tipe == long:241 return _IntegerCaster()242 if tipe == float:243 return _FloatCaster()244 if tipe == str:245 return _StringCaster()246 if tipe == bool:247 return _BooleanCaster()248 if tipe == list:249 return _ListCaster()250 if tipe == tuple:251 return _TupleCaster()252 if tipe == dict:253 return _DictionaryCaster()254 except:255 if _modulename(s): # This will go away in future versions.256 return _ModuleWrapperCaster()257 if _plugin(s):258 return _PluginCaster()259 raise ConfigLoaderException("Cannot resolve type : %s." % s)260 except Exception, e:261 raise ConfigLoaderException(\262 'Internal exception while trying to convert %s -- %s' % (s, e))263 raise ConfigLoaderException('Unsupported type: %s.' % type(tipe))264 265 290 class ConfigFactory: 266 291 '''Factory for managing multiple named configurations. … … 297 322 if config: self.loaded[name] = config 298 323 299 300 324 configFactory = ConfigFactory() 301 325 302 303 304 326 ############################################################################### 305 327 ## -- Private utility functions … … 315 337 return True 316 338 317 def _modulename(name): 318 modname_pattern = re.compile(r'^([a-zA-Z]\w*(\.[a-zA-Z]\w*)?)+$') 319 return modname_pattern.match(name) is not None 339 #def _modulename(name): 340 # modname_pattern = re.compile(r'^([a-zA-Z]\w*(\.[a-zA-Z]\w*)?)+$') 341 # return modname_pattern.match(name) is not None 320 342 321 343 def _plugin(strng): … … 323 345 return plugin_patt.match(strng) is not None 324 346 325 ## -- end Private utility functions 326 ############################################################################### 347 def _flat(seq): 348 flat = [] 349 for inner in seq: 350 flat = flat + inner 351 return flat 352 353 def cast(loader, val): 354 ns = dict(loader.plugins) 355 ns['__val__'] = None 356 exec('__val__=%s' % val, ns, ns) 357 return ns['__val__'] 327 358 359 ## -- end Private utility functions 328 360 ############################################################################### 329 # -------- INTERNAL ---------- Loaders for various types ---------------------330 ###############################################################################331 332 333 class _Caster:334 def _exec(self, val):335 ns = {}336 exec("val=%s" % val, ns, ns)337 return ns["val"]338 def __call__(self, val):339 return self._exec(val)340 341 class _IntegerCaster(_Caster):342 def __call__(self, val):343 return int(val)344 345 class _FloatCaster(_Caster):346 def __call__(self, val):347 return float(val)348 349 class _StringCaster(_Caster):350 def __call__(self, val):351 return str(val)[1:-1] # get rid of quotes352 353 class _BooleanCaster(_Caster):354 def __call__(self, val):355 return "True" == val356 357 class _ListCaster(_Caster):358 pass359 360 class _TupleCaster(_Caster):361 pass362 363 class _DictionaryCaster(_Caster):364 pass365 366 class _ModuleWrapperCaster(_Caster):367 def __call__(self, val):368 return ModuleWrapper(val)369 370 class _PluginCaster(_Caster):371 def __call__(self, val):372 ns = dict(ConfigLoader.plugins)373 ns['__val__'] = None374 exec('__val__=%s' % val, ns, ns)375 return ns['__val__']376 361 377 #__all__ = allexcept("IConfig", "IConfigLoader", "IConfigFactory",378 # "providedBy", "implements", "allexcept", "ModuleWrapper") -
trunk/xix/utils/python.py
r159 r199 19 19 from interfaces import IModuleWrapper 20 20 from comp.interface import implements 21 import inspect 21 22 import warnings 23 import sys &nb
