bug fix: util.lower_case(str)
[lazy-man.git] / util.py
blob52321c27072460c4ba0ea454543ec1d0bfbbfba0
1 import os
2 import sys
3 import operator
4 import re
5 from glob import glob
7 class BlockStream:
8 tab_stop = ' '
9 Debug, Info, Warning, Error = 1, 0, -1, -2
10 threshold = Info
11 def __init__(self, stream=sys.stdout, level=Info, indent=0):
12 self.stream, self.level, self.indent = stream, level, indent
14 def new(self, level=None):
15 if level==None: level = self.level
16 return BlockStream(self.stream, level, self.indent+1)
18 def out(self, content):
19 if self.level > self.threshold:return
20 self.stream.writelines(["%s%s\n"%(self._get_indent(), line) for line in content.split('\n')])
22 def _get_indent(self):
23 return self.tab_stop * self.indent
25 def __lshift__(self, content):
26 self.out(content)
28 def list_(li):
29 if type(li) == list or type(li) == tuple:
30 return reduce(operator.add, map(list_, li), [])
31 else:
32 return [li]
34 def files(*arg):
35 return list_([glob(item) for item in list_(arg)])
37 def ext(filelist_, suffix):
38 def _ext(file_name, suffix):
39 return re.sub('\.\w+$', '.%s'%suffix, file_name)
40 return [_ext(file, suffix) for file in list_(filelist_)]
42 def update_file(name, content):
43 def need_update(name, content):
44 if not os.path.exists(name):
45 return True
46 return open(name).read() != content
47 if need_update(name, content):
48 file = open(name, 'w')
49 file.write(content)
50 file.close()
51 return True
52 return False
54 def lower_case(str):
55 return '_'.join(filter(None, re.split('([A-Z][a-z]+)', str))).lower()
57 class Env(dict):
58 def __init__(self, d={}, **kw):
59 dict.__init__(self)
60 self.update(d, **kw)
62 def __getattr__(self, name):
63 return self.get(name)
65 def mget(mlist, **args):
66 def match(item):
67 for key, value in args.items():
68 if not item.has_key(key):
69 return False
70 if item[key] != value:
71 return False
72 return True
73 return filter(match, mlist)
75 class Templet:
76 def __init__(self, str):
77 self.str = str
79 def sub(self, sep=' ', env={}, **kw):
80 preprocessed = re.sub('\$(\w+)', '${\\1}', self.str)
81 segments = re.split('(?s)(\${.+?})', preprocessed)
82 env.update(**kw)
83 def evil(seg):
84 if not re.match('\$', seg):
85 return seg
86 exp = re.sub('(?s)^\${(.+?)}', '\\1', seg)
87 result = eval(exp, globals(), env)
88 return sep.join([str(item) for item in list_(result)])
89 return ''.join([evil(seg) for seg in segments])
91 def sub(template, env={}, sep=' ', **kw):
92 return Templet(template).sub(env=env, sep=sep, **kw)
94 class TagNotMatch(Exception):
95 def __init__(self, begin, end):
96 self.begin, self.end = begin, end
98 def __str__(self):
99 return 'Tag does not match: %s %s'%(self.begin, self.end)
101 class Sed:
102 def __init__(self, comment='#'):
103 self.comment = comment
105 @staticmethod
106 def _split(str, comment):
107 sep1 = '(^%s\s*@\w+.*?\s*\n)' %(comment)
108 sep2 = '(^%s\s*!<(?:\w+).*?^%s (?:\w+)>!\s*\n)' %(comment, comment)
109 sep = '%s|%s'%(sep1, sep2)
110 sep = re.compile(sep, re.M|re.S)
111 return filter(None, re.split(sep, str))
113 @staticmethod
114 def _tag(str, comment):
115 tag1 = '^%s\s*@(\w+)(.*)\s*\n' %(comment)
116 tag2 = '^%s\s*!<(\w+)(.*)^%s (\w+)>!\s*\n'%(comment, comment)
117 tag1 = re.compile(tag1)
118 tag2 = re.compile(tag2, re.M|re.S)
119 m1 = re.match(tag1, str)
120 m2 = re.match(tag2, str)
121 if m1:
122 tag, content = m1.groups()
123 return tag, content
124 elif m2:
125 begin_tag, content, end_tag = m2.groups()
126 if begin_tag != end_tag:
127 raise TagNotMatch(begin_tag, end_tag)
128 return begin_tag, content
129 else:
130 return 'normal', str
132 def gen_chunk(self, str):
133 return '%s !<gen\n%s\n%s gen>!\n' %(self.comment, str, self.comment)
135 def _chunk(self, str):
136 chunks = self._split(str, self.comment)
137 return [self._tag(str, self.comment) + (str,) for str in chunks]
139 def sed(self, str):
140 chunk_list = self._chunk(str)
141 new_chunk_list = [getattr(self, tag)(content, raw) for tag, content, raw in chunk_list]
142 return ''.join(new_chunk_list)
144 def update(self, file_name):
145 new_file = self.sed(open(file_name).read())
146 return update_file(file_name, new_file)
148 def normal(self, content, raw):
149 return raw
151 def gen(self, content, raw):
152 return ''