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