17 | | # GNU General Public License for more det |
| 16 | # GNU General Public License for more details. |
| 17 | # |
| 18 | # You should have received a copy of the GNU General Public License |
| 19 | # along with this program; if not, write to the Free Software |
| 20 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 21 | # |
| 22 | # Version 0.1 |
| 23 | # This program is used to parse django's urlconf file. It can deal with standard |
| 24 | # urls.py , e.g., it can parse prefix, pattern, method, and extra dictionary. |
| 25 | # How to use it: |
| 26 | # |
| 27 | # from DjangoUrlConf import URLConf |
| 28 | # #URLConf can receive a usrconf filename, or leave it empty |
| 29 | # u = URLConf([urlsfile]) |
| 30 | # #add common pattern |
| 31 | # u.add(r'^test/$', 'newtest.test.main') |
| 32 | # #add include pattern |
| 33 | # u.add(r'^ajax/input/$', "include('newtest.test.ajax')") |
| 34 | # #easyadd, it can automaticaly add '^' at the begin and '$' at the end |
| 35 | # u.easyadd('tttt/input/', 'newtest.test.main') |
| 36 | # #you can also pass it a dict variable |
| 37 | # u.easyadd('tttt/input/', 'newtest.test.main', {'template': 'my_calendar/calendar'}) |
| 38 | # #you can find a pattern |
| 39 | # u.find(r'^ajax/input/$') |
| 40 | # #or easyfind a pattern |
| 41 | # u.easyfind('ajax/input/') |
| 42 | # #find mapping method |
| 43 | # u.has_method('newtest.test.ajax') |
| 44 | # #save to a file, if the filename is omit, then use the filename which passwd to URLConf class |
| 45 | # u.save([filename]) |
| 46 | |
| 47 | import sys |
| 48 | |
| 49 | class URLPatterns: |
| 50 | def __init__(self): |
| 51 | self.orders = [] |
| 52 | self.prefix = '' |
| 53 | self.nodes = {} |
| 54 | |
| 55 | def render(self): |
| 56 | s = ['urlpatterns = patterns(%s\n' % self.prefix] |
| 57 | for key in self.orders: |
| 58 | if not self.nodes.has_key(key) : |
| 59 | s.append(key) |
| 60 | else: |
| 61 | s.append(self.render_item(key)) |
| 62 | s.append(")\n") |
| 63 | return ''.join(s) |
| 64 | |
| 65 | def render_item(self, key): |
| 66 | s = [] |
| 67 | p, d = self.nodes[key] |
| 68 | if not p.startswith('include('): |
| 69 | p = repr(p) |
| 70 | s.append(" (r%r, %s" % (key, p)) |
| 71 | if d: |
| 72 | if isinstance(d, dict): |
| 73 | d = repr(d) |
| 74 | s.append(", %s),\n" % d) |
| 75 | else: |
| 76 | s.append("),\n") |
| 77 | return ''.join(s) |
| 78 | |
| 79 | def parse(self, text): |
| 80 | text = text.replace('\r\n', '\n') |
| 81 | text = text.replace('\r', '\n') |
| 82 | |
| 83 | i = 0 |
| 84 | last = 0 |
| 85 | flag = 0 #0 begin 1 comment 2 pattern |
| 86 | while i<len(text): |
| 87 | #skip blank |
| 88 | while text[i] in (' ', '\t'): |
| 89 | i += 1 |
| 90 | if text[i] == '#': #if comment: |
| 91 | while text[i] != '\n': |
| 92 | i += 1 |
| 93 | i += 1 |
| 94 | self.orders.append(text[last:i]) |
| 95 | last = i |
| 96 | elif text[i] == '(': |
| 97 | i += 1 |
| 98 | last = i |
| 99 | level = 1 |
| 100 | while level != 0: |
| 101 | if text[i] == '(': |
| 102 | level += 1 |
| 103 | elif text[i] == ')': |
| 104 | level -= 1 |
| 105 | i += 1 |
| 106 | t = text[last:i-1] |
| 107 | pos = t.find(',') |
| 108 | if pos > -1: |
| 109 | key = eval(t[:pos]) |
| 110 | pos += 1 |
| 111 | begin = pos |
| 112 | pos = t.find(',', pos) |
| 113 | if pos > -1: |
| 114 | pattern = t[begin:pos].lstrip() |
| 115 | dict = t[pos+1:].rstrip() |
| 116 | else: |
| 117 | pattern = t[begin:].strip() |
| 118 | dict = None |
| 119 | if key not in self.orders: |
| 120 | self.orders.append(key) |
| 121 | self.nodes[key] = (pattern, dict) |
| 122 | while text[i] != '\n': |
| 123 | i += 1 |
| 124 | i += 1 |
| 125 | last = i |
| 126 | else: |
| 127 | while i < len(text) and text[i] != '\n': |
| 128 | i += 1 |
| 129 | i += 1 |
| 130 | self.orders.append(text[last:i]) |
| 131 | last = i |
| 132 | |
| 133 | self.orders.pop(-1) |
| 134 | |
| 135 | |
| 136 | def remove(self, key): |
| 137 | if self.nodes.has_key(key): |
| 138 | s = self.render_item(key) |
| 139 | del self.nodes[key] |
| 140 | pos = self.orders.index(key) |
| 141 | self.orders[pos] = '#' + s |
| 142 | |
| 143 | def find(self, pattern): |
| 144 | return self.nodes.get(pattern, None) |
| 145 | |
| 146 | def add(self, pattern, method, dict=None): |
| 147 | if pattern not in self.orders: |
| 148 | self.orders.append(pattern) |
| 149 | self.nodes[pattern] = (method, dict) |
| 150 | |
| 151 | def has_method(self, method): |
| 152 | for key, v in self.nodes(): |
| 153 | p, d = v |
| 154 | if p == method: |
| 155 | return key |
| 156 | return None |
| 157 | |
| 158 | |
| 159 | class URLConf: |
| 160 | def __init__(self, urlconf_filename=''): |
| 161 | self.nodes = [] |
| 162 | self.urlconf = URLPatterns() |
| 163 | self.filename = urlconf_filename |
| 164 | self.read(self.filename) |
| 165 | |
| 166 | def out(self): |
| 167 | self.save(sys.stdout) |
| 168 | |
| 169 | def save(self, filename=None): |
| 170 | if not filename: |
| 171 | filename = self.filename |
| 172 | if isinstance(filename, (str, unicode)): |
| 173 | f = file(filename, 'w') |
| 174 | else: |
| 175 | f = filename |
| 176 | text = [] |
| 177 | for node in self.nodes: |
| 178 | if isinstance(node, URLPatterns): |
| 179 | text.append(node.render()) |
| 180 | else: |
| 181 | if isinstance(node, (list, tuple)): |
| 182 | text.append(''.join(node)) |
| 183 | else: |
| 184 | text.append(node) |
| 185 | s = ''.join(text) |
| 186 | if s.find('from django.conf.urls.defaults import *') == -1: |
| 187 | s = 'from django.conf.urls.defaults import *\n\n' + s |
| 188 | |
| 189 | f.write(s) |
| 190 | |
| 191 | |
| 192 | def find(self, pattern): |
| 193 | return self.urlconf.find(pattern, None) |
| 194 | |
| 195 | def easyfind(self, pattern): |
| 196 | pattern = '^%s$' % pattern |
| 197 | return self.find(pattern, None) |
| 198 | |
| 199 | def add(self, pattern, method, dict=None): |
| 200 | self.urlconf.add(pattern, method, dict) |
| 201 | |
| 202 | def easyadd(self, pattern, method, dict=None): |
| 203 | pattern = '^%s$' % pattern |
| 204 | self.add(pattern, method, dict) |
| 205 | |
| 206 | def has_method(self, method): |
| 207 | return self.urlconf.has_method(method) |
| 208 | |
| 209 | def read(self, filename): |
| 210 | if not filename: |
| 211 | self.nodes.append(self.urlconf) |
| 212 | return |
| 213 | |
| 214 | f = file(filename) |
| 215 | for line in f: |
| 216 | if not line.startswith('urlpatterns'): |
| 217 | self.nodes.append(line) |
| 218 | else: |
| 219 | begin = line.rfind('(') |
| 220 | end = line.rfind(',') |
| 221 | self.urlconf.prefix = line[begin+1:end] |
| 222 | t = f.next() |
| 223 | s = [] |
| 224 | while t.strip() != ')': |
| 225 | s.append(t) |
| 226 | t = f.next() |
| 227 | self.urlconf.parse(''.join(s+[')'])) |
| 228 | self.nodes.append(self.urlconf) |
| 229 | |
| 230 | if __name__ == '__main__': |
| 231 | # u = URLConf('urls.py') |
| 232 | u = URLConf() |
| 233 | # print u.find('^ajax/input/$') |
| 234 | u.add('^test/$', 'newtest.test.main') |
| 235 | u.add('^ajax/input/$', "include('newtest.test.ajax')") |
| 236 | u.easyadd('tttt/input/', 'newtest.test.main') |
| 237 | u.easyadd('tttt/input/', 'newtest.test.main', {'template': 'my_calendar/calendar'}) |
| 238 | u.out() |