# HG changeset patch # User Sylvain Thénault # Date 1253023397 -7200 # Node ID e454590f1b80eec81133a5f291a815f166114703 # Parent 7ac07c3a965990f2b0fd740e42615e5ba4c3fc08# Parent eccb7380dc3b28422d0329d19985c7636fc1ae54 remerge diff -r 7ac07c3a9659 -r e454590f1b80 test/unittest_utils.py --- a/test/unittest_utils.py Tue Sep 15 16:02:07 2009 +0200 +++ b/test/unittest_utils.py Tue Sep 15 16:03:17 2009 +0200 @@ -8,7 +8,11 @@ from logilab.common.testlib import TestCase, unittest_main -from cubicweb.utils import make_uid, UStringIO, SizeConstrainedList +import simplejson +import decimal +import datetime + +from cubicweb.utils import make_uid, UStringIO, SizeConstrainedList, CubicWebJsonEncoder class MakeUidTC(TestCase): @@ -48,6 +52,24 @@ l.extend(extension) yield self.assertEquals, l, expected +class JSONEncoerTests(TestCase): + + def encode(self, value): + return simplejson.dumps(value, cls=CubicWebJsonEncoder) + + def test_encoding_dates(self): + self.assertEquals(self.encode(datetime.datetime(2009, 9, 9, 20, 30)), + '"2009/09/09 20:30:00"') + self.assertEquals(self.encode(datetime.date(2009, 9, 9)), + '"2009/09/09"') + self.assertEquals(self.encode(datetime.time(20, 30)), + '"20:30:00"') + + def test_encoding_decimal(self): + self.assertEquals(self.encode(decimal.Decimal('1.2')), '1.2') + + def test_encoding_unknown_stuff(self): + self.assertEquals(self.encode(TestCase), 'null') if __name__ == '__main__': unittest_main() diff -r 7ac07c3a9659 -r e454590f1b80 utils.py --- a/utils.py Tue Sep 15 16:02:07 2009 +0200 +++ b/utils.py Tue Sep 15 16:03:17 2009 +0200 @@ -11,10 +11,14 @@ import locale from md5 import md5 +import datetime as pydatetime from datetime import datetime, timedelta, date from time import time, mktime from random import randint, seed from calendar import monthrange +import decimal + +import simplejson # initialize random seed from current time seed() @@ -348,3 +352,22 @@ return False __answer[0] = True return True + + +class CubicWebJsonEncoder(simplejson.JSONEncoder): + """define a simplejson encoder to be able to encode yams std types""" + def default(self, obj): + if isinstance(obj, pydatetime.datetime): + return obj.strftime('%Y/%m/%d %H:%M:%S') + elif isinstance(obj, pydatetime.date): + return obj.strftime('%Y/%m/%d') + elif isinstance(obj, pydatetime.time): + return obj.strftime('%H:%M:%S') + elif isinstance(obj, decimal.Decimal): + return float(obj) + try: + return simplejson.JSONEncoder.default(self, obj) + except TypeError: + # we never ever want to fail because of an unknown type, + # just return None in those cases. + return None diff -r 7ac07c3a9659 -r e454590f1b80 web/data/cubicweb.edition.js --- a/web/data/cubicweb.edition.js Tue Sep 15 16:02:07 2009 +0200 +++ b/web/data/cubicweb.edition.js Tue Sep 15 16:03:17 2009 +0200 @@ -354,7 +354,7 @@ // Success if (result[0]) { if (onsuccess) { - onsuccess(result[1], formid); + onsuccess(result, formid); } else { document.location.href = result[1]; } diff -r 7ac07c3a9659 -r e454590f1b80 web/views/basecontrollers.py --- a/web/views/basecontrollers.py Tue Sep 15 16:02:07 2009 +0200 +++ b/web/views/basecontrollers.py Tue Sep 15 16:03:17 2009 +0200 @@ -11,6 +11,7 @@ __docformat__ = "restructuredtext en" from smtplib import SMTP +import datetime import simplejson @@ -181,48 +182,54 @@ break return (foreid, ex.errors) + def _validate_form(req, vreg): # XXX should use the `RemoteCallFailed` mechanism try: ctrl = vreg['controllers'].select('edit', req=req) except NoSelectableObject: - return (False, {None: req._('not authorized')}) + return (False, {None: req._('not authorized')}, None) try: ctrl.publish(None) except ValidationError, ex: - return (False, _validation_error(req, ex)) + return (False, _validation_error(req, ex), ctrl._edited_entity) except Redirect, ex: + if ctrl._edited_entity: + ctrl._edited_entity.complete() try: req.cnx.commit() # ValidationError may be raise on commit except ValidationError, ex: - return (False, _validation_error(req, ex)) + return (False, _validation_error(req, ex), ctrl._edited_entity) else: - return (True, ex.location) + return (True, ex.location, ctrl._edited_entity) except Exception, ex: req.cnx.rollback() req.exception('unexpected error while validating form') - return (False, req._(str(ex).decode('utf-8'))) - return (False, '???') + return (False, req._(str(ex).decode('utf-8')), ctrl._edited_entity) + return (False, '???', None) class FormValidatorController(Controller): id = 'validateform' - def response(self, domid, status, args): + def response(self, domid, status, args, entity): + callback = str(self.req.form.get('__onsuccess', 'null')) + errback = str(self.req.form.get('__onfailure', 'null')) self.req.set_content_type('text/html') - jsargs = simplejson.dumps( (status, args) ) + jsargs = simplejson.dumps((status, args, entity), cls=CubicWebJsonEncoder) return """""" % (domid, jsargs) + wp = window.parent; + window.parent.handleFormValidationResponse('%s', %s, %s, %s); +""" % (domid, callback, errback, jsargs) def publish(self, rset=None): self.req.json_request = True # XXX unclear why we have a separated controller here vs # js_validate_form on the json controller - status, args = _validate_form(self.req, self.vreg) + status, args, entity = _validate_form(self.req, self.vreg) domid = self.req.form.get('__domid', 'entityForm').encode( self.req.encoding) - return self.response(domid, status, args) + return self.response(domid, status, args, entity) class JSonController(Controller):