Package buildbot :: Module stringTemplate
[frames] | no frames]

Source Code for Module buildbot.stringTemplate

  1  """A copy of the string Template class from python 2.4, included  
  2  for compatibility with python 2.3. 
  3  """ 
  4   
  5  import re as _re 
  6   
7 -class _multimap:
8 """Helper class for combining multiple mappings. 9 10 Used by .{safe_,}substitute() to combine the mapping and keyword 11 arguments. 12 """
13 - def __init__(self, primary, secondary):
14 self._primary = primary 15 self._secondary = secondary
16
17 - def __getitem__(self, key):
18 try: 19 return self._primary[key] 20 except KeyError: 21 return self._secondary[key]
22 23
24 -class _TemplateMetaclass(type):
25 pattern = r""" 26 %(delim)s(?: 27 (?P<escaped>%(delim)s) | # Escape sequence of two delimiters 28 (?P<named>%(id)s) | # delimiter and a Python identifier 29 {(?P<braced>%(id)s)} | # delimiter and a braced identifier 30 (?P<invalid>) # Other ill-formed delimiter exprs 31 ) 32 """ 33
34 - def __init__(cls, name, bases, dct):
35 super(_TemplateMetaclass, cls).__init__(name, bases, dct) 36 if 'pattern' in dct: 37 pattern = cls.pattern 38 else: 39 pattern = _TemplateMetaclass.pattern % { 40 'delim' : _re.escape(cls.delimiter), 41 'id' : cls.idpattern, 42 } 43 cls.pattern = _re.compile(pattern, _re.IGNORECASE | _re.VERBOSE)
44 45
46 -class Template:
47 """A string class for supporting $-substitutions.""" 48 __metaclass__ = _TemplateMetaclass 49 50 delimiter = '$' 51 idpattern = r'[_a-z][_a-z0-9]*' 52
53 - def __init__(self, template):
54 self.template = template
55 56 # Search for $$, $identifier, ${identifier}, and any bare $'s 57
58 - def _invalid(self, mo):
59 i = mo.start('invalid') 60 lines = self.template[:i].splitlines(True) 61 if not lines: 62 colno = 1 63 lineno = 1 64 else: 65 colno = i - len(''.join(lines[:-1])) 66 lineno = len(lines) 67 raise ValueError('Invalid placeholder in string: line %d, col %d' % 68 (lineno, colno))
69
70 - def substitute(self, *args, **kws):
71 if len(args) > 1: 72 raise TypeError('Too many positional arguments') 73 if not args: 74 mapping = kws 75 elif kws: 76 mapping = _multimap(kws, args[0]) 77 else: 78 mapping = args[0] 79 # Helper function for .sub() 80 def convert(mo): 81 # Check the most common path first. 82 named = mo.group('named') or mo.group('braced') 83 if named is not None: 84 val = mapping[named] 85 # We use this idiom instead of str() because the latter will 86 # fail if val is a Unicode containing non-ASCII characters. 87 return '%s' % val 88 if mo.group('escaped') is not None: 89 return self.delimiter 90 if mo.group('invalid') is not None: 91 self._invalid(mo) 92 raise ValueError('Unrecognized named group in pattern', 93 self.pattern)
94 return self.pattern.sub(convert, self.template)
95
96 - def safe_substitute(self, *args, **kws):
97 if len(args) > 1: 98 raise TypeError('Too many positional arguments') 99 if not args: 100 mapping = kws 101 elif kws: 102 mapping = _multimap(kws, args[0]) 103 else: 104 mapping = args[0] 105 # Helper function for .sub() 106 def convert(mo): 107 named = mo.group('named') 108 if named is not None: 109 try: 110 # We use this idiom instead of str() because the latter 111 # will fail if val is a Unicode containing non-ASCII 112 return '%s' % mapping[named] 113 except KeyError: 114 return self.delimiter + named 115 braced = mo.group('braced') 116 if braced is not None: 117 try: 118 return '%s' % mapping[braced] 119 except KeyError: 120 return self.delimiter + '{' + braced + '}' 121 if mo.group('escaped') is not None: 122 return self.delimiter 123 if mo.group('invalid') is not None: 124 return self.delimiter 125 raise ValueError('Unrecognized named group in pattern', 126 self.pattern)
127 return self.pattern.sub(convert, self.template) 128