test_dynamicobjectmapping.py (9960B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\cherrypy\test\test_dynamicobjectmapping.py 2 import cherrypy 3 from cherrypy._cptree import Application 4 from cherrypy.test import helper 5 script_names = ['', 6 '/foo', 7 '/users/fred/blog', 8 '/corp/blog'] 9 10 def setup_server(): 11 12 class SubSubRoot: 13 14 def index(self): 15 return 'SubSubRoot index' 16 17 index.exposed = True 18 19 def default(self, *args): 20 return 'SubSubRoot default' 21 22 default.exposed = True 23 24 def handler(self): 25 return 'SubSubRoot handler' 26 27 handler.exposed = True 28 29 def dispatch(self): 30 return 'SubSubRoot dispatch' 31 32 dispatch.exposed = True 33 34 subsubnodes = {'1': SubSubRoot(), 35 '2': SubSubRoot()} 36 37 class SubRoot: 38 39 def index(self): 40 return 'SubRoot index' 41 42 index.exposed = True 43 44 def default(self, *args): 45 return 'SubRoot %s' % (args,) 46 47 default.exposed = True 48 49 def handler(self): 50 return 'SubRoot handler' 51 52 handler.exposed = True 53 54 def _cp_dispatch(self, vpath): 55 return subsubnodes.get(vpath[0], None) 56 57 subnodes = {'1': SubRoot(), 58 '2': SubRoot()} 59 60 class Root: 61 62 def index(self): 63 return 'index' 64 65 index.exposed = True 66 67 def default(self, *args): 68 return 'default %s' % (args,) 69 70 default.exposed = True 71 72 def handler(self): 73 return 'handler' 74 75 handler.exposed = True 76 77 def _cp_dispatch(self, vpath): 78 return subnodes.get(vpath[0]) 79 80 class User(object): 81 82 def __init__(self, id, name): 83 self.id = id 84 self.name = name 85 86 def __unicode__(self): 87 return unicode(self.name) 88 89 user_lookup = {1: User(1, 'foo'), 90 2: User(2, 'bar')} 91 92 def make_user(name, id = None): 93 if not id: 94 id = max(*user_lookup.keys()) + 1 95 user_lookup[id] = User(id, name) 96 return id 97 98 class UserContainerNode(object): 99 exposed = True 100 101 def POST(self, name): 102 return 'POST %d' % make_user(name) 103 104 def GET(self): 105 keys = user_lookup.keys() 106 keys.sort() 107 return unicode(keys) 108 109 def dynamic_dispatch(self, vpath): 110 try: 111 id = int(vpath[0]) 112 except (ValueError, IndexError): 113 return None 114 115 return UserInstanceNode(id) 116 117 class UserInstanceNode(object): 118 exposed = True 119 120 def __init__(self, id): 121 self.id = id 122 self.user = user_lookup.get(id, None) 123 if not self.user and cherrypy.request.method != 'PUT': 124 raise cherrypy.HTTPError(404) 125 126 def GET(self, *args, **kwargs): 127 return unicode(self.user) 128 129 def POST(self, name): 130 self.user.name = name 131 return 'POST %d' % self.user.id 132 133 def PUT(self, name): 134 if self.user: 135 self.user.name = name 136 return 'PUT %d' % self.user.id 137 else: 138 return 'PUT %d' % make_user(name, self.id) 139 140 def DELETE(self): 141 id = self.user.id 142 del user_lookup[self.user.id] 143 del self.user 144 return 'DELETE %d' % id 145 146 class ABHandler: 147 148 class CustomDispatch: 149 150 def index(self, a, b): 151 return 'custom' 152 153 index.exposed = True 154 155 def _cp_dispatch(self, vpath): 156 return self.CustomDispatch() 157 158 def index(self, a, b = None): 159 body = ['a:' + str(a)] 160 if b is not None: 161 body.append(',b:' + str(b)) 162 return ''.join(body) 163 164 index.exposed = True 165 166 def delete(self, a, b): 167 return 'deleting ' + str(a) + ' and ' + str(b) 168 169 delete.exposed = True 170 171 class IndexOnly: 172 173 def _cp_dispatch(self, vpath): 174 while vpath: 175 vpath.pop() 176 177 return self 178 179 def index(self): 180 return 'IndexOnly index' 181 182 index.exposed = True 183 184 class DecoratedPopArgs: 185 186 def index(self): 187 return 'no params' 188 189 index.exposed = True 190 191 def hi(self): 192 return "hi was not interpreted as 'a' param" 193 194 hi.exposed = True 195 196 DecoratedPopArgs = cherrypy.popargs('a', 'b', handler=ABHandler())(DecoratedPopArgs) 197 198 class NonDecoratedPopArgs: 199 _cp_dispatch = cherrypy.popargs('a') 200 201 def index(self, a): 202 return 'index: ' + str(a) 203 204 index.exposed = True 205 206 class ParameterizedHandler: 207 208 def __init__(self, a): 209 self.a = a 210 211 def index(self): 212 if 'a' in cherrypy.request.params: 213 raise Exception('Parameterized handler argument ended up in request.params') 214 return self.a 215 216 index.exposed = True 217 218 class ParameterizedPopArgs: 219 pass 220 221 ParameterizedPopArgs = cherrypy.popargs('a', handler=ParameterizedHandler)(ParameterizedPopArgs) 222 Root.decorated = DecoratedPopArgs() 223 Root.undecorated = NonDecoratedPopArgs() 224 Root.index_only = IndexOnly() 225 Root.parameter_test = ParameterizedPopArgs() 226 Root.users = UserContainerNode() 227 md = cherrypy.dispatch.MethodDispatcher('dynamic_dispatch') 228 for url in script_names: 229 conf = {'/': {'user': (url or '/').split('/')[-2]}, 230 '/users': {'request.dispatch': md}} 231 cherrypy.tree.mount(Root(), url, conf) 232 233 234 class DynamicObjectMappingTest(helper.CPWebCase): 235 setup_server = staticmethod(setup_server) 236 237 def testObjectMapping(self): 238 for url in script_names: 239 prefix = self.script_name = url 240 self.getPage('/') 241 self.assertBody('index') 242 self.getPage('/handler') 243 self.assertBody('handler') 244 self.getPage('/1/') 245 self.assertBody('SubRoot index') 246 self.getPage('/2/') 247 self.assertBody('SubRoot index') 248 self.getPage('/1/handler') 249 self.assertBody('SubRoot handler') 250 self.getPage('/2/handler') 251 self.assertBody('SubRoot handler') 252 self.getPage('/asdf/') 253 self.assertBody("default ('asdf',)") 254 self.getPage('/asdf/asdf') 255 self.assertBody("default ('asdf', 'asdf')") 256 self.getPage('/asdf/handler') 257 self.assertBody("default ('asdf', 'handler')") 258 self.getPage('/1/1/') 259 self.assertBody('SubSubRoot index') 260 self.getPage('/2/2/') 261 self.assertBody('SubSubRoot index') 262 self.getPage('/1/1/handler') 263 self.assertBody('SubSubRoot handler') 264 self.getPage('/2/2/handler') 265 self.assertBody('SubSubRoot handler') 266 self.getPage('/2/2/dispatch') 267 self.assertBody('SubSubRoot dispatch') 268 self.getPage('/2/2/foo/foo') 269 self.assertBody('SubSubRoot default') 270 self.getPage('/1/asdf/') 271 self.assertBody("SubRoot ('asdf',)") 272 self.getPage('/1/asdf/asdf') 273 self.assertBody("SubRoot ('asdf', 'asdf')") 274 self.getPage('/1/asdf/handler') 275 self.assertBody("SubRoot ('asdf', 'handler')") 276 277 def testMethodDispatch(self): 278 self.getPage('/users') 279 self.assertBody('[1, 2]') 280 self.assertHeader('Allow', 'GET, HEAD, POST') 281 self.getPage('/users', method='POST', body='name=baz') 282 self.assertBody('POST 3') 283 self.assertHeader('Allow', 'GET, HEAD, POST') 284 self.getPage('/users/5', method='POST', body='name=baz') 285 self.assertStatus(404) 286 self.getPage('/users/5', method='PUT', body='name=boris') 287 self.assertBody('PUT 5') 288 self.assertHeader('Allow', 'DELETE, GET, HEAD, POST, PUT') 289 self.getPage('/users') 290 self.assertBody('[1, 2, 3, 5]') 291 self.assertHeader('Allow', 'GET, HEAD, POST') 292 test_cases = ((1, 'foo', 'fooupdated', 'DELETE, GET, HEAD, POST, PUT'), 293 (2, 'bar', 'barupdated', 'DELETE, GET, HEAD, POST, PUT'), 294 (3, 'baz', 'bazupdated', 'DELETE, GET, HEAD, POST, PUT'), 295 (5, 'boris', 'borisupdated', 'DELETE, GET, HEAD, POST, PUT')) 296 for id, name, updatedname, headers in test_cases: 297 self.getPage('/users/%d' % id) 298 self.assertBody(name) 299 self.assertHeader('Allow', headers) 300 self.getPage('/users/%d' % id, method='POST', body='name=%s' % updatedname) 301 self.assertBody('POST %d' % id) 302 self.assertHeader('Allow', headers) 303 self.getPage('/users/%d' % id, method='PUT', body='name=%s' % updatedname) 304 self.assertBody('PUT %d' % id) 305 self.assertHeader('Allow', headers) 306 self.getPage('/users/%d' % id, method='DELETE') 307 self.assertBody('DELETE %d' % id) 308 self.assertHeader('Allow', headers) 309 310 self.getPage('/users') 311 self.assertBody('[]') 312 self.assertHeader('Allow', 'GET, HEAD, POST') 313 314 def testVpathDispatch(self): 315 self.getPage('/decorated/') 316 self.assertBody('no params') 317 self.getPage('/decorated/hi') 318 self.assertBody("hi was not interpreted as 'a' param") 319 self.getPage('/decorated/yo/') 320 self.assertBody('a:yo') 321 self.getPage('/decorated/yo/there/') 322 self.assertBody('a:yo,b:there') 323 self.getPage('/decorated/yo/there/delete') 324 self.assertBody('deleting yo and there') 325 self.getPage('/decorated/yo/there/handled_by_dispatch/') 326 self.assertBody('custom') 327 self.getPage('/undecorated/blah/') 328 self.assertBody('index: blah') 329 self.getPage('/index_only/a/b/c/d/e/f/g/') 330 self.assertBody('IndexOnly index') 331 self.getPage('/parameter_test/argument2/') 332 self.assertBody('argument2')