[registry|ajaxcontroller] the @ajaxcontroller decorator ought to return a compatible object (closes #2385155)
--- a/cwvreg.py Thu Jun 07 18:33:53 2012 +0200
+++ b/cwvreg.py Fri Jun 08 16:47:07 2012 +0200
@@ -256,6 +256,12 @@
key=lambda x: x.cw_propval('order'))
+def related_appobject(obj, appobjectattr='__appobject__'):
+ """ adapts any object to a potential appobject bound to it
+ through the __appobject__ attribute
+ """
+ return getattr(obj, appobjectattr, obj)
+
class ETypeRegistry(CWRegistry):
@@ -272,6 +278,7 @@
self.clear_caches()
def register(self, obj, **kwargs):
+ obj = related_appobject(obj)
oid = kwargs.get('oid') or obj.__regid__
if oid != 'Any' and not oid in self.schema:
self.error('don\'t register %s, %s type not defined in the '
@@ -537,6 +544,20 @@
def itervalues(self):
return (value for key, value in self.items())
+ def load_module(self, module):
+ """ variation from the base implementation:
+ apply related_appobject to the automatically registered objects
+ """
+ self.info('loading %s from %s', module.__name__, module.__file__)
+ if hasattr(module, 'registration_callback'):
+ module.registration_callback(self)
+ return
+ for objname, obj in vars(module).iteritems():
+ if objname.startswith('_'):
+ continue
+ self._load_ancestors_then_object(module.__name__,
+ related_appobject(obj))
+
def reset(self):
CW_EVENT_MANAGER.emit('before-registry-reset', self)
super(CWRegistryStore, self).reset()
@@ -552,6 +573,17 @@
self.register_property(key, **propdef)
CW_EVENT_MANAGER.emit('after-registry-reset', self)
+ def register_all(self, objects, modname, butclasses=()):
+ butclasses = set(related_appobject(obj)
+ for obj in butclasses)
+ objects = [related_appobject(obj) for obj in objects]
+ super(CWRegistryStore, self).register_all(objects, modname, butclasses)
+
+ def register_and_replace(self, obj, replaced):
+ obj = related_appobject(obj)
+ replaced = related_appobject(replaced)
+ super(CWRegistryStore, self).register_and_replace(obj, replaced)
+
def set_schema(self, schema):
"""set instance'schema and load application objects"""
self._set_schema(schema)
@@ -624,6 +656,7 @@
If `clear` is true, all objects with the same identifier will be
previously unregistered.
"""
+ obj = related_appobject(obj)
super(CWRegistryStore, self).register(obj, *args, **kwargs)
# XXX bw compat
ifaces = use_interfaces(obj)
--- a/web/test/unittest_views_basecontrollers.py Thu Jun 07 18:33:53 2012 +0200
+++ b/web/test/unittest_views_basecontrollers.py Fri Jun 08 16:47:07 2012 +0200
@@ -695,38 +695,44 @@
@ajaxfunc
def foo(self, x, y):
return 'hello'
- self.assertTrue(issubclass(foo, AjaxFunction))
- self.assertEqual(foo.__regid__, 'foo')
- self.assertEqual(foo.check_pageid, False)
- self.assertEqual(foo.output_type, None)
+ self.assertEqual(foo(object, 1, 2), 'hello')
+ appobject = foo.__appobject__
+ self.assertTrue(issubclass(appobject, AjaxFunction))
+ self.assertEqual(appobject.__regid__, 'foo')
+ self.assertEqual(appobject.check_pageid, False)
+ self.assertEqual(appobject.output_type, None)
req = self.request()
- f = foo(req)
+ f = appobject(req)
self.assertEqual(f(12, 13), 'hello')
def test_ajaxfunc_checkpageid(self):
- @ajaxfunc( check_pageid=True)
+ @ajaxfunc(check_pageid=True)
def foo(self, x, y):
- pass
- self.assertTrue(issubclass(foo, AjaxFunction))
- self.assertEqual(foo.__regid__, 'foo')
- self.assertEqual(foo.check_pageid, True)
- self.assertEqual(foo.output_type, None)
+ return 'hello'
+ self.assertEqual(foo(object, 1, 2), 'hello')
+ appobject = foo.__appobject__
+ self.assertTrue(issubclass(appobject, AjaxFunction))
+ self.assertEqual(appobject.__regid__, 'foo')
+ self.assertEqual(appobject.check_pageid, True)
+ self.assertEqual(appobject.output_type, None)
# no pageid
req = self.request()
- f = foo(req)
+ f = appobject(req)
self.assertRaises(RemoteCallFailed, f, 12, 13)
def test_ajaxfunc_json(self):
@ajaxfunc(output_type='json')
def foo(self, x, y):
return x + y
- self.assertTrue(issubclass(foo, AjaxFunction))
- self.assertEqual(foo.__regid__, 'foo')
- self.assertEqual(foo.check_pageid, False)
- self.assertEqual(foo.output_type, 'json')
+ self.assertEqual(foo(object, 1, 2), 3)
+ appobject = foo.__appobject__
+ self.assertTrue(issubclass(appobject, AjaxFunction))
+ self.assertEqual(appobject.__regid__, 'foo')
+ self.assertEqual(appobject.check_pageid, False)
+ self.assertEqual(appobject.output_type, 'json')
# no pageid
req = self.request()
- f = foo(req)
+ f = appobject(req)
self.assertEqual(f(12, 13), '25')
--- a/web/views/ajaxcontroller.py Thu Jun 07 18:33:53 2012 +0200
+++ b/web/views/ajaxcontroller.py Fri Jun 08 16:47:07 2012 +0200
@@ -283,11 +283,21 @@
if data is None:
raise RemoteCallFailed(self._cw._('pageid-not-found'))
return self.serialize(implementation(self, *args, **kwargs))
+
AnAjaxFunc.__name__ = implementation.__name__
# make sure __module__ refers to the original module otherwise
# vreg.register(obj) will ignore ``obj``.
AnAjaxFunc.__module__ = implementation.__module__
- return AnAjaxFunc
+ # relate the ``implementation`` object to its wrapper appobject
+ # will be used by e.g.:
+ # import base_module
+ # @ajaxfunc
+ # def foo(self):
+ # return 42
+ # assert foo(object) == 42
+ # vreg.register_and_replace(foo, base_module.older_foo)
+ implementation.__appobject__ = AnAjaxFunc
+ return implementation
def ajaxfunc(implementation=None, selector=yes(), output_type=None,